Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change static fields emits #43114

Merged
merged 41 commits into from
Jun 25, 2021
Merged

Conversation

Kingwl
Copy link
Contributor

@Kingwl Kingwl commented Mar 6, 2021

Fixes #36267

TODO:

  • Update transformer.
    • transform this
    • transform super
    • esnext, es6, es5
    • useDefineForClassFields
  • Avoid errors in checker.
    • this in static context
    • super in static context
  • Add more tersts.
    • this
    • super
    • new this
    • super call
    • complex expression
    • function boundary
    • arrow function boundary
    • class boundary

@typescript-bot typescript-bot added the For Milestone Bug PRs that fix a bug with a specific milestone label Mar 6, 2021
@Kingwl Kingwl marked this pull request as ready for review March 6, 2021 17:15
@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 6, 2021

@rbuckton Sorry for bothering. But take a look please.

@sandersn
Copy link
Member

Before I look at the PR, I remember talking to @rbuckton about this last year and getting confused about how to make decorators work after he pointed out that they could be troublesome. Can you add some tests with decorated classes?
(or point me to the existing ones, although I didn't see any filenames with 'decorator' in them).

@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 22, 2021

Added a basic test.

It's really confused.... tc39/proposal-decorators#329
I think an acceptable solution is disallow static this reference in a class who has decorator. (It's just stage 2 :XD)

@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 22, 2021

I think we could just replace this to some variable, the same as the class name reference:

@foo
class C {
  static a = 1
  static b = 1 + C.a
  static c = () => C.b
  static d = () => this.b
}

to

var C_1;
let C = C_1 = class C {
};
C.a = 1;
C.b = 1 + C_1.a;
C.c = () => C_1.b;
C.d = () => C_1.b;
C = C_1 = __decorate([
    foo
], C);

It's seems does not break anything.

@rbuckton
Copy link
Member

this and Decorators is confusing. The direction that the decorators proposal seems to be going is that static initializers (field init and static {}) will be applied before decorators are run since a class decorator acts on a fully evaluated class. So this would refer to the undecorated class (and so would C, which differs from TypeScript today). If you wanted to refer to the decorated class (if a decorator performed constructor replacement), you would need to do something like this:

let C = @decorator class { 
  static x = 1;
  static y = this.x; // refers to undecorated class
  static z = C.y; // TDZ error since C hasn't been initialized yet.
  static w = () => C.y; // Ok if called after C is initialized.
}

@rbuckton rbuckton mentioned this pull request Mar 23, 2021
3 tasks
@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 23, 2021

So I guess the correct emit should be:

@foo
class C {
  static a = 1
  static b = 1 + C.a
  static c = () => C.b
  static d = () => this.b
}
var C_1, C_2; // a variable to keep undecorated class
let C = C_1 = C_2 = class C {
};
C.a = 1;
C.b = 1 + C_1.a;
C.c = () => C_1.b;
C.d = () => C_2.b; // this reference to  undecorated class
C = C_1 = __decorate([
    foo
], C);

Or we just denied this one because the decorator proposal is not stable yet?
It's might be break if we do something not clear yet.

BTW: Seems we does not support decorator on class expression (#42198)...

@rbuckton
Copy link
Member

I discussed this with the TC39 Decorator stakeholders group. There's no final answer on how class decorators should interact with this in static initializers at this time. For now it would be best to just ban the combination and report an error if you use a class decorator on a class with a static initializer that uses this. I'd be tempted to say we should emit (void 0) in place of this when encountering this combination during transformation so people don't just // @ts-ignore the error and rely on broken behavior.

@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 25, 2021

Thanks!

@rbuckton
Copy link
Member

By the way, static private fields and static methods and accessors just landed in master, so you will want to rebase.

@Kingwl
Copy link
Contributor Author

Kingwl commented Mar 25, 2021

Oh. I just realized. Should we error and avoid the super keyword in static class field initializer?

@rbuckton
Copy link
Member

super() would be disallowed, but not super.x. This works today in v8:

class A { static x = 1 }
class B extends A { static y = super.x }
B.y; // 1

@Kingwl
Copy link
Contributor Author

Kingwl commented Jun 25, 2021

Oh wow. Thanks for your hard working.

@rbuckton rbuckton requested review from sandersn and weswigham June 25, 2021 09:46
@rbuckton
Copy link
Member

@sandersn, @weswigham can either of you review my changes to this PR? In general I think this is fairly close to ready. I'd like to merge tomorrow morning for the 4.4 beta if possible.

@Kingwl
Copy link
Contributor Author

Kingwl commented Jun 25, 2021

Well... A huge update.

# Conflicts:
#	src/compiler/checker.ts
#	src/compiler/transformers/classFields.ts
Copy link
Member

@weswigham weswigham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we have a reserved name error if you attempt to transpile a class/variable named Reflect, since it's referenced in emit now?

@rbuckton
Copy link
Member

Should we have a reserved name error if you attempt to transpile a class/variable named Reflect, since it's referenced in emit now?

Probably, yes. Once I get this in static {} working I'll look into it in a follow-on PR.

@rbuckton
Copy link
Member

I've just about finished adding this support to static {}, should have this updated shortly.

@rbuckton
Copy link
Member

Something that will need a bit more time to consider after this has merged is how control flow should affect the types of static properties:

class C {
  static x; // infers type through control-flow
  static {
    this.x = 1;
  }
}

This is similar to what we do for constructor() {}, except you can have multiple static {} blocks. I have a temporary solution in place currently, but I think we will need to rethink control flow in a class long term. For example:

class C {
  static x;
  static { this.x = 1; }
  static y = this.x; // y should have type `number`
  static { this.x++; } // this.x should have type `number`
}

@rbuckton
Copy link
Member

The last update fixes some use-before-def errors. I also added support for strict property initialization for statics, but I think I will actually revert that since it would be a possible breaking change and we haven't had the opportunity to discuss it in design meeting.

@rbuckton rbuckton force-pushed the change_static_fields_emits branch from 28c870d to 9850dc3 Compare June 25, 2021 22:06
@rbuckton
Copy link
Member

@typescript-bot perf test
@typescript-bot run dt
@typescript-bot test this
@typescript-bot user test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 25, 2021

Heya @rbuckton, I've started to run the perf test suite on this PR at 9850dc3. You can monitor the build here.

Update: The results are in!

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 25, 2021

Heya @rbuckton, I've started to run the parallelized community code test suite on this PR at 9850dc3. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 25, 2021

Heya @rbuckton, I've started to run the parallelized Definitely Typed test suite on this PR at 9850dc3. You can monitor the build here.

@typescript-bot
Copy link
Collaborator

typescript-bot commented Jun 25, 2021

Heya @rbuckton, I've started to run the extended test suite on this PR at 9850dc3. You can monitor the build here.

Copy link
Member

@rbuckton rbuckton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to review the various test suite results before merging, but I think this looks good.

@rbuckton
Copy link
Member

@RyanCavanaugh, depending on the test results this should be ready to merge shortly.

@rbuckton
Copy link
Member

  • User/Docker tests are failing, but it looks like an issue with the test suite. As a result I can't tell if there's any differences due to this PR.
  • Only difference in RWC seems to be a minor change in source map emit, but nothing concerning.
  • I don't imagine there will be issues with DT since this shouldn't affect declaration files.

Currently I'm just waiting on the perf results.

@typescript-bot
Copy link
Collaborator

@rbuckton
The results of the perf run you requested are in!

Here they are:

Comparison Report - main..43114

Metric main 43114 Delta Best Worst
Angular - node (v10.16.3, x64)
Memory used 344,260k (± 0.02%) 344,370k (± 0.02%) +110k (+ 0.03%) 344,217k 344,490k
Parse Time 1.80s (± 0.36%) 1.79s (± 0.47%) -0.01s (- 0.39%) 1.78s 1.82s
Bind Time 0.84s (± 0.59%) 0.84s (± 0.59%) 0.00s ( 0.00%) 0.83s 0.85s
Check Time 5.39s (± 0.47%) 5.39s (± 0.78%) +0.00s (+ 0.06%) 5.29s 5.46s
Emit Time 5.60s (± 0.71%) 5.78s (± 0.29%) +0.18s (+ 3.21%) 5.75s 5.83s
Total Time 13.62s (± 0.38%) 13.80s (± 0.40%) +0.18s (+ 1.32%) 13.67s 13.94s
Compiler-Unions - node (v10.16.3, x64)
Memory used 201,383k (± 0.03%) 201,521k (± 0.04%) +138k (+ 0.07%) 201,359k 201,685k
Parse Time 0.78s (± 0.67%) 0.78s (± 0.79%) +0.00s (+ 0.26%) 0.77s 0.80s
Bind Time 0.53s (± 0.95%) 0.52s (± 1.13%) -0.00s (- 0.19%) 0.51s 0.54s
Check Time 7.82s (± 0.83%) 7.83s (± 0.29%) +0.02s (+ 0.23%) 7.79s 7.88s
Emit Time 2.29s (± 0.99%) 2.43s (± 0.75%) +0.14s (+ 6.06%) 2.40s 2.47s
Total Time 11.41s (± 0.63%) 11.57s (± 0.28%) +0.16s (+ 1.41%) 11.50s 11.63s
Monaco - node (v10.16.3, x64)
Memory used 340,569k (± 0.03%) 340,713k (± 0.03%) +144k (+ 0.04%) 340,483k 340,907k
Parse Time 1.46s (± 0.72%) 1.44s (± 0.73%) -0.01s (- 0.89%) 1.42s 1.46s
Bind Time 0.74s (± 0.75%) 0.75s (± 0.94%) +0.01s (+ 1.49%) 0.74s 0.77s
Check Time 5.44s (± 0.66%) 5.45s (± 0.55%) +0.01s (+ 0.18%) 5.36s 5.49s
Emit Time 3.00s (± 1.02%) 3.16s (± 1.25%) +0.16s (+ 5.23%) 3.10s 3.28s
Total Time 10.64s (± 0.33%) 10.80s (± 0.42%) +0.17s (+ 1.58%) 10.69s 10.92s
TFS - node (v10.16.3, x64)
Memory used 303,850k (± 0.02%) 303,947k (± 0.02%) +98k (+ 0.03%) 303,823k 304,072k
Parse Time 1.18s (± 0.56%) 1.17s (± 0.65%) -0.01s (- 0.42%) 1.16s 1.19s
Bind Time 0.71s (± 0.42%) 0.71s (± 0.91%) +0.00s (+ 0.56%) 0.70s 0.73s
Check Time 4.96s (± 0.30%) 4.96s (± 0.55%) +0.00s (+ 0.04%) 4.91s 5.02s
Emit Time 3.13s (± 1.05%) 3.36s (± 2.02%) +0.24s (+ 7.65%) 3.24s 3.53s
Total Time 9.98s (± 0.40%) 10.22s (± 0.77%) +0.24s (+ 2.41%) 10.03s 10.43s
material-ui - node (v10.16.3, x64)
Memory used 470,885k (± 0.01%) 470,975k (± 0.02%) +90k (+ 0.02%) 470,840k 471,125k
Parse Time 1.72s (± 0.32%) 1.71s (± 0.64%) -0.01s (- 0.29%) 1.68s 1.73s
Bind Time 0.66s (± 0.84%) 0.67s (± 0.75%) +0.00s (+ 0.45%) 0.65s 0.67s
Check Time 14.14s (± 0.29%) 14.11s (± 0.24%) -0.03s (- 0.20%) 14.05s 14.19s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 16.52s (± 0.24%) 16.49s (± 0.25%) -0.03s (- 0.19%) 16.42s 16.59s
Angular - node (v12.1.0, x64)
Memory used 322,510k (± 0.03%) 322,583k (± 0.03%) +74k (+ 0.02%) 322,434k 322,765k
Parse Time 1.77s (± 0.70%) 1.76s (± 0.78%) -0.01s (- 0.51%) 1.74s 1.80s
Bind Time 0.82s (± 0.57%) 0.83s (± 0.41%) +0.01s (+ 1.59%) 0.83s 0.84s
Check Time 5.25s (± 0.28%) 5.26s (± 0.47%) +0.01s (+ 0.19%) 5.18s 5.30s
Emit Time 5.82s (± 0.47%) 6.01s (± 0.70%) +0.18s (+ 3.14%) 5.93s 6.10s
Total Time 13.67s (± 0.32%) 13.86s (± 0.34%) +0.20s (+ 1.43%) 13.75s 13.96s
Compiler-Unions - node (v12.1.0, x64)
Memory used 188,766k (± 0.11%) 188,804k (± 0.12%) +37k (+ 0.02%) 188,344k 189,118k
Parse Time 0.77s (± 0.62%) 0.77s (± 0.61%) -0.00s (- 0.39%) 0.76s 0.78s
Bind Time 0.53s (± 0.76%) 0.53s (± 0.75%) +0.00s (+ 0.38%) 0.52s 0.54s
Check Time 7.32s (± 0.44%) 7.35s (± 0.38%) +0.02s (+ 0.33%) 7.28s 7.40s
Emit Time 2.32s (± 1.09%) 2.44s (± 1.14%) +0.13s (+ 5.53%) 2.38s 2.51s
Total Time 10.93s (± 0.43%) 11.09s (± 0.34%) +0.15s (+ 1.38%) 11.00s 11.17s
Monaco - node (v12.1.0, x64)
Memory used 323,602k (± 0.06%) 323,771k (± 0.06%) +169k (+ 0.05%) 322,947k 323,998k
Parse Time 1.42s (± 0.57%) 1.41s (± 0.79%) -0.01s (- 1.06%) 1.39s 1.44s
Bind Time 0.71s (± 0.84%) 0.72s (± 0.46%) +0.00s (+ 0.70%) 0.71s 0.73s
Check Time 5.29s (± 0.48%) 5.29s (± 0.55%) +0.00s (+ 0.08%) 5.25s 5.37s
Emit Time 3.05s (± 0.49%) 3.17s (± 1.11%) +0.12s (+ 4.00%) 3.11s 3.28s
Total Time 10.47s (± 0.38%) 10.59s (± 0.51%) +0.12s (+ 1.12%) 10.50s 10.71s
TFS - node (v12.1.0, x64)
Memory used 288,554k (± 0.03%) 288,616k (± 0.02%) +62k (+ 0.02%) 288,483k 288,732k
Parse Time 1.19s (± 0.89%) 1.19s (± 0.56%) -0.00s (- 0.17%) 1.18s 1.21s
Bind Time 0.69s (± 0.81%) 0.69s (± 1.27%) +0.01s (+ 0.73%) 0.67s 0.71s
Check Time 4.88s (± 0.48%) 4.88s (± 0.39%) -0.00s (- 0.00%) 4.83s 4.92s
Emit Time 3.22s (± 0.94%) 3.33s (± 0.62%) +0.11s (+ 3.42%) 3.28s 3.38s
Total Time 9.98s (± 0.39%) 10.09s (± 0.33%) +0.11s (+ 1.09%) 10.04s 10.19s
material-ui - node (v12.1.0, x64)
Memory used 449,506k (± 0.06%) 449,512k (± 0.08%) +6k (+ 0.00%) 448,494k 449,861k
Parse Time 1.70s (± 0.52%) 1.71s (± 0.48%) +0.00s (+ 0.18%) 1.69s 1.72s
Bind Time 0.64s (± 0.96%) 0.65s (± 0.56%) +0.01s (+ 0.78%) 0.64s 0.65s
Check Time 12.75s (± 0.51%) 12.76s (± 0.81%) +0.01s (+ 0.10%) 12.64s 13.15s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.09s (± 0.47%) 15.11s (± 0.70%) +0.02s (+ 0.15%) 14.99s 15.51s
Angular - node (v14.15.1, x64)
Memory used 321,134k (± 0.01%) 321,226k (± 0.01%) +93k (+ 0.03%) 321,195k 321,260k
Parse Time 1.79s (± 0.50%) 1.80s (± 0.59%) +0.00s (+ 0.11%) 1.78s 1.82s
Bind Time 0.87s (± 0.54%) 0.87s (± 0.56%) +0.00s (+ 0.46%) 0.87s 0.89s
Check Time 5.25s (± 0.50%) 5.24s (± 0.35%) -0.01s (- 0.15%) 5.20s 5.29s
Emit Time 5.95s (± 1.05%) 6.07s (± 0.62%) +0.12s (+ 2.05%) 5.95s 6.12s
Total Time 13.86s (± 0.59%) 13.98s (± 0.35%) +0.12s (+ 0.87%) 13.81s 14.07s
Compiler-Unions - node (v14.15.1, x64)
Memory used 187,899k (± 0.38%) 188,033k (± 0.38%) +134k (+ 0.07%) 187,665k 190,929k
Parse Time 0.80s (± 0.50%) 0.80s (± 0.65%) -0.00s (- 0.25%) 0.79s 0.81s
Bind Time 0.56s (± 0.80%) 0.56s (± 0.53%) +0.00s (+ 0.00%) 0.55s 0.56s
Check Time 7.47s (± 0.52%) 7.46s (± 0.39%) -0.00s (- 0.04%) 7.40s 7.52s
Emit Time 2.31s (± 0.83%) 2.43s (± 1.00%) +0.11s (+ 4.89%) 2.38s 2.49s
Total Time 11.14s (± 0.43%) 11.25s (± 0.39%) +0.11s (+ 0.97%) 11.17s 11.32s
Monaco - node (v14.15.1, x64)
Memory used 322,569k (± 0.01%) 322,579k (± 0.00%) +10k (+ 0.00%) 322,555k 322,612k
Parse Time 1.47s (± 0.60%) 1.48s (± 0.34%) +0.00s (+ 0.07%) 1.47s 1.49s
Bind Time 0.75s (± 0.86%) 0.75s (± 0.69%) -0.00s (- 0.40%) 0.74s 0.76s
Check Time 5.23s (± 0.35%) 5.27s (± 0.57%) +0.04s (+ 0.80%) 5.22s 5.36s
Emit Time 3.10s (± 0.37%) 3.21s (± 0.32%) +0.11s (+ 3.42%) 3.20s 3.24s
Total Time 10.55s (± 0.25%) 10.70s (± 0.30%) +0.15s (+ 1.40%) 10.65s 10.79s
TFS - node (v14.15.1, x64)
Memory used 287,513k (± 0.00%) 287,655k (± 0.01%) +143k (+ 0.05%) 287,631k 287,699k
Parse Time 1.27s (± 1.58%) 1.25s (± 0.77%) -0.02s (- 1.81%) 1.23s 1.28s
Bind Time 0.71s (± 0.81%) 0.72s (± 0.51%) +0.00s (+ 0.42%) 0.71s 0.72s
Check Time 4.90s (± 0.46%) 4.92s (± 0.37%) +0.01s (+ 0.22%) 4.89s 4.96s
Emit Time 3.27s (± 0.63%) 3.41s (± 0.66%) +0.14s (+ 4.15%) 3.35s 3.45s
Total Time 10.16s (± 0.57%) 10.29s (± 0.25%) +0.13s (+ 1.27%) 10.24s 10.35s
material-ui - node (v14.15.1, x64)
Memory used 447,879k (± 0.06%) 448,018k (± 0.03%) +139k (+ 0.03%) 447,407k 448,155k
Parse Time 1.76s (± 0.66%) 1.75s (± 0.76%) -0.00s (- 0.11%) 1.74s 1.80s
Bind Time 0.68s (± 0.87%) 0.69s (± 1.01%) +0.01s (+ 1.02%) 0.68s 0.71s
Check Time 12.96s (± 0.59%) 12.94s (± 0.60%) -0.02s (- 0.15%) 12.82s 13.09s
Emit Time 0.00s (± 0.00%) 0.00s (± 0.00%) 0.00s ( NaN%) 0.00s 0.00s
Total Time 15.39s (± 0.51%) 15.38s (± 0.53%) -0.01s (- 0.09%) 15.25s 15.54s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-206-generic
Architecturex64
Available Memory16 GB
Available Memory1 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v10.16.3, x64)
  • node (v12.1.0, x64)
  • node (v14.15.1, x64)
Scenarios
  • Angular - node (v10.16.3, x64)
  • Angular - node (v12.1.0, x64)
  • Angular - node (v14.15.1, x64)
  • Compiler-Unions - node (v10.16.3, x64)
  • Compiler-Unions - node (v12.1.0, x64)
  • Compiler-Unions - node (v14.15.1, x64)
  • Monaco - node (v10.16.3, x64)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v14.15.1, x64)
  • TFS - node (v10.16.3, x64)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v14.15.1, x64)
  • material-ui - node (v10.16.3, x64)
  • material-ui - node (v12.1.0, x64)
  • material-ui - node (v14.15.1, x64)
Benchmark Name Iterations
Current 43114 10
Baseline main 10

Developer Information:

Download Benchmark

@rbuckton
Copy link
Member

Perf tests seem like a negligible change. There's an increase in emit time, but I think that can be addressed next week.

@rbuckton
Copy link
Member

I will also follow up next week with the reserved name error.

@rbuckton rbuckton merged commit dc237b3 into microsoft:main Jun 25, 2021
@Kingwl
Copy link
Contributor Author

Kingwl commented Jun 26, 2021

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
For Milestone Bug PRs that fix a bug with a specific milestone
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Referencing this from a static class field
6 participants