-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Implement Static Private Class Elements #42986
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
Changes from all commits
e3a3fb8
4ab27a2
6977b9f
bc8c07e
2760ed8
04af85d
f048d72
f8cfb81
4aa4c3b
0ac1271
7da5bd9
e133f60
aa5dd8a
a3889a7
8952caa
dee87bb
aec7e9b
f3bbf0f
a1b59cd
6b74498
d51f6cd
c175770
4301af5
3a056b2
95df2d1
590124e
219ea83
25da8ca
a2228be
ff4f737
704727c
73925dc
67fd38d
45c2a41
356b91d
b391464
5ebb3d6
7006c09
b876613
31a8c00
9219e99
5a27a32
964fc27
d2ab6fc
23f6c67
374e6f3
62b4f2f
b2a692d
363041e
64757e0
68a7f80
7e7b0b1
30c7f69
c924058
e65116f
4748c87
09a5aae
497e47f
294cc48
027bdb3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,19 @@ namespace ts { | |
| // Class Fields Helpers | ||
| createClassPrivateFieldGetHelper(receiver: Expression, privateField: Identifier): Expression; | ||
| createClassPrivateFieldSetHelper(receiver: Expression, privateField: Identifier, value: Expression): Expression; | ||
| createClassPrivateMethodGetHelper(receiver: Expression, instances: Identifier, fn: Identifier): Expression; | ||
| createClassPrivateReadonlyHelper(receiver: Expression, value: Expression): Expression; | ||
| createClassPrivateWriteonlyHelper(receiver: Expression): Expression; | ||
| createClassPrivateAccessorGetHelper(receiver: Expression, instances: Identifier, fn: Identifier): Expression; | ||
| createClassPrivateAccessorSetHelper(receiver: Expression, instances: Identifier, fn: Identifier, value: Expression): Expression; | ||
| // Class Static Private Helpers | ||
| createClassStaticPrivateFieldGetHelper(receiver: Expression, classConstructor: Identifier, privateField: Identifier): Expression; | ||
| createClassStaticPrivateFieldSetHelper(receiver: Expression, classConstructor: Identifier, privateField: Identifier, value: Expression): Expression; | ||
| createClassStaticPrivateMethodGetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier): Expression; | ||
| createClassStaticPrivateReadonlyHelper(receiver: Expression, value: Expression): Expression; | ||
| createClassStaticPrivateWriteonlyHelper(receiver: Expression): Expression; | ||
| createClassStaticPrivateAccessorGetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier): Expression; | ||
| createClassStaticPrivateAccessorSetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier, value: Expression): Expression; | ||
|
Comment on lines
+37
to
+49
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This adds a large number of emit helpers that are extremely similar. Perhaps we could condense them down? In #42458 I suggested extending the existing |
||
| } | ||
|
|
||
| export function createEmitHelperFactory(context: TransformationContext): EmitHelperFactory { | ||
|
|
@@ -72,6 +85,18 @@ namespace ts { | |
| // Class Fields Helpers | ||
| createClassPrivateFieldGetHelper, | ||
| createClassPrivateFieldSetHelper, | ||
| createClassPrivateMethodGetHelper, | ||
| createClassPrivateReadonlyHelper, | ||
| createClassPrivateWriteonlyHelper, | ||
| createClassPrivateAccessorGetHelper, | ||
| createClassPrivateAccessorSetHelper, | ||
| createClassStaticPrivateFieldGetHelper, | ||
| createClassStaticPrivateFieldSetHelper, | ||
| createClassStaticPrivateMethodGetHelper, | ||
| createClassStaticPrivateReadonlyHelper, | ||
| createClassStaticPrivateWriteonlyHelper, | ||
| createClassStaticPrivateAccessorGetHelper, | ||
| createClassStaticPrivateAccessorSetHelper, | ||
| }; | ||
|
|
||
| /** | ||
|
|
@@ -377,6 +402,66 @@ namespace ts { | |
| context.requestEmitHelper(classPrivateFieldSetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldSet"), /*typeArguments*/ undefined, [receiver, privateField, value]); | ||
| } | ||
|
|
||
| function createClassPrivateMethodGetHelper(receiver: Expression, instances: Identifier, fn: Identifier) { | ||
| context.requestEmitHelper(classPrivateMethodGetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classPrivateMethodGet"), /*typeArguments*/ undefined, [receiver, instances, fn]); | ||
| } | ||
|
|
||
| function createClassPrivateReadonlyHelper(receiver: Expression, value: Expression) { | ||
| context.requestEmitHelper(classPrivateReadonlyHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classPrivateReadonly"), /*typeArguments*/ undefined, [receiver, value]); | ||
| } | ||
|
|
||
| function createClassPrivateWriteonlyHelper(receiver: Expression) { | ||
| context.requestEmitHelper(classPrivateWriteonlyHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classPrivateWriteonly"), /*typeArguments*/ undefined, [receiver]); | ||
| } | ||
|
|
||
| function createClassPrivateAccessorGetHelper(receiver: Expression, instances: Identifier, fn: Identifier) { | ||
| context.requestEmitHelper(classPrivateAccessorGetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classPrivateAccessorGet"), /*typeArguments*/ undefined, [receiver, instances, fn]); | ||
| } | ||
|
|
||
| function createClassPrivateAccessorSetHelper(receiver: Expression, instances: Identifier, fn: Identifier, value: Expression) { | ||
| context.requestEmitHelper(classPrivateAccessorSetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classPrivateAccessorSet"), /*typeArguments*/ undefined, [receiver, instances, fn, value]); | ||
| } | ||
| // Class Private Static Helpers | ||
| function createClassStaticPrivateFieldGetHelper(receiver: Expression, classConstructor: Identifier, privateField: Identifier) { | ||
| context.requestEmitHelper(classStaticPrivateFieldGetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateFieldGet"), /*typeArguments*/ undefined, [receiver, classConstructor, privateField]); | ||
| } | ||
|
|
||
| function createClassStaticPrivateFieldSetHelper(receiver: Expression, classConstructor: Identifier, privateField: Identifier, value: Expression) { | ||
| context.requestEmitHelper(classStaticPrivateFieldSetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateFieldSet"), /*typeArguments*/ undefined, [receiver, classConstructor, privateField, value]); | ||
| } | ||
|
|
||
| function createClassStaticPrivateMethodGetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier) { | ||
| context.requestEmitHelper(classStaticPrivateMethodGetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateMethodGet"), /*typeArguments*/ undefined, [receiver, classConstructor, fn]); | ||
| } | ||
|
|
||
| function createClassStaticPrivateReadonlyHelper(receiver: Expression, value: Expression) { | ||
| context.requestEmitHelper(classStaticPrivateReadonlyHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateReadonly"), /*typeArguments*/ undefined, [receiver, value]); | ||
| } | ||
|
|
||
| function createClassStaticPrivateWriteonlyHelper(receiver: Expression) { | ||
| context.requestEmitHelper(classStaticPrivateWriteonlyHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateWriteonly"), /*typeArguments*/ undefined, [receiver]); | ||
| } | ||
|
|
||
| function createClassStaticPrivateAccessorGetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier) { | ||
| context.requestEmitHelper(classStaticPrivateAccessorGetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateAccessorGet"), /*typeArguments*/ undefined, [receiver, classConstructor, fn]); | ||
| } | ||
|
|
||
| function createClassStaticPrivateAccessorSetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier, value: Expression) { | ||
| context.requestEmitHelper(classStaticPrivateAccessorSetHelper); | ||
| return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateAccessorSet"), /*typeArguments*/ undefined, [receiver, classConstructor, fn, value]); | ||
| } | ||
| } | ||
|
|
||
| /* @internal */ | ||
|
|
@@ -844,6 +929,159 @@ namespace ts { | |
| };` | ||
| }; | ||
|
|
||
| export const classPrivateMethodGetHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classPrivateMethodGet", | ||
| importName: "__classPrivateMethodGet", | ||
| scoped: false, | ||
| text: ` | ||
| var __classPrivateMethodGet = (this && this.__classPrivateMethodGet) || function (receiver, instances, fn) { | ||
| if (!instances.has(receiver)) { | ||
| throw new TypeError("attempted to get private method on non-instance"); | ||
| } | ||
| return fn; | ||
| };` | ||
| }; | ||
|
|
||
| export const classPrivateReadonlyHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classPrivateReadonly", | ||
| importName: "__classPrivateReadonly", | ||
| scoped: false, | ||
| text: ` | ||
| var __classPrivateReadonly = (this && this.__classPrivateReadonly) || function () { | ||
| throw new TypeError("private element is not writable"); | ||
| };` | ||
| }; | ||
|
|
||
| export const classPrivateWriteonlyHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classPrivateWriteonly", | ||
| importName: "__classPrivateWriteonly", | ||
| scoped: false, | ||
| text: ` | ||
| var __classPrivateWriteonly = (this && this.__classPrivateWriteonly) || function () { | ||
| throw new TypeError("private setter was defined without a getter"); | ||
| };` | ||
| }; | ||
|
|
||
| export const classPrivateAccessorGetHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classPrivateAccessorGet", | ||
| importName: "__classPrivateAccessorGet", | ||
| scoped: false, | ||
| text: ` | ||
| var __classPrivateAccessorGet = (this && this.__classPrivateAccessorGet) || function (receiver, instances, fn) { | ||
| if (!instances.has(receiver)) { | ||
| throw new TypeError("attempted to get private accessor on non-instance"); | ||
| } | ||
| return fn.call(receiver); | ||
| };` | ||
| }; | ||
|
|
||
| export const classPrivateAccessorSetHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classPrivateAccessorSet", | ||
| importName: "__classPrivateAccessorSet", | ||
| scoped: false, | ||
| text: ` | ||
| var __classPrivateAccessorSet = (this && this.__classPrivateAccessorSet) || function (receiver, instances, fn, value) { | ||
| if (!instances.has(receiver)) { | ||
| throw new TypeError("attempted to set private accessor on non-instance"); | ||
| } | ||
| fn.call(receiver, value); | ||
| return value; | ||
| };` | ||
| }; | ||
|
|
||
| export const classStaticPrivateFieldGetHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classStaticPrivateFieldGet", | ||
| importName: "__classStaticPrivateFieldGet", | ||
| scoped: false, | ||
| text: ` | ||
| var __classStaticPrivateFieldGet = (this && this.__classStaticPrivateFieldGet) || function (receiver, classConstructor, propertyDescriptor) { | ||
| if (receiver !== classConstructor) { | ||
| throw new TypeError("Private static access of wrong provenance"); | ||
| } | ||
| if (propertyDescriptor === undefined) { | ||
| throw new TypeError("Private static field was accessed before its declaration."); | ||
| } | ||
| return propertyDescriptor.value; | ||
| };` | ||
| }; | ||
|
|
||
| export const classStaticPrivateFieldSetHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classStaticPrivateFieldSet", | ||
| importName: "__classStaticPrivateFieldSet", | ||
| scoped: false, | ||
| text: ` | ||
| var __classStaticPrivateFieldSet = (this && this.__classStaticPrivateFieldSet) || function (receiver, classConstructor, propertyDescriptor, value) { | ||
| if (receiver !== classConstructor) { | ||
| throw new TypeError("Private static access of wrong provenance"); | ||
| } | ||
| if (propertyDescriptor === undefined) { | ||
| throw new TypeError("Private static field was accessed before its declaration."); | ||
| } | ||
| propertyDescriptor.value = value; | ||
| return value; | ||
| };` | ||
| }; | ||
|
|
||
| export const classStaticPrivateMethodGetHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classStaticPrivateMethodGet", | ||
| importName: "__classStaticPrivateMethodGet", | ||
| scoped: false, | ||
| text: ` | ||
| var __classStaticPrivateMethodGet = (this && this.__classStaticPrivateMethodGet) || function (receiver, classConstructor, fn) { | ||
| if (receiver !== classConstructor) { | ||
| throw new TypeError("Private static access of wrong provenance"); | ||
| } | ||
| return fn; | ||
| };` | ||
| }; | ||
|
|
||
| export const classStaticPrivateReadonlyHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classStaticPrivateReadonly", | ||
| importName: "__classStaticPrivateReadonly", | ||
| scoped: false, | ||
| text: ` | ||
| var __classStaticPrivateReadonly = (this && this.__classStaticPrivateReadonly) || function () { | ||
| throw new TypeError("Private static element is not writable"); | ||
| };` | ||
| }; | ||
|
|
||
| export const classStaticPrivateWriteonlyHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classStaticPrivateWriteonly", | ||
| importName: "__classStaticPrivateWriteonly", | ||
| scoped: false, | ||
| text: ` | ||
| var __classStaticPrivateWriteonly = (this && this.__classStaticPrivateWriteonly) || function () { | ||
| throw new TypeError("Private static element is not readable"); | ||
| };` | ||
| }; | ||
|
|
||
| export const classStaticPrivateAccessorGetHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classStaticPrivateAccessorGet", | ||
| importName: "__classStaticPrivateAccessorGet", | ||
| scoped: false, | ||
| text: ` | ||
| var __classStaticPrivateAccessorGet = (this && this.__classStaticPrivateAccessorGet) || function (receiver, classConstructor, fn) { | ||
| if (receiver !== classConstructor) { | ||
| throw new TypeError("Private static access of wrong provenance"); | ||
| } | ||
| return fn.call(receiver); | ||
| };` | ||
| }; | ||
|
|
||
| export const classStaticPrivateAccessorSetHelper: UnscopedEmitHelper = { | ||
| name: "typescript:classStaticPrivateAccessorSet", | ||
| importName: "__classStaticPrivateAccessorSet", | ||
| scoped: false, | ||
| text: ` | ||
| var __classStaticPrivateAccessorSet = (this && this.__classStaticPrivateAccessorSet) || function (receiver, classConstructor, fn, value) { | ||
| if (receiver !== classConstructor) { | ||
| throw new TypeError("Private static access of wrong provenance"); | ||
| } | ||
| fn.call(receiver, value); | ||
| return value; | ||
| };` | ||
| }; | ||
|
|
||
| let allUnscopedEmitHelpers: ReadonlyESMap<string, UnscopedEmitHelper> | undefined; | ||
|
|
||
| export function getAllUnscopedEmitHelpers() { | ||
|
|
@@ -869,6 +1107,11 @@ namespace ts { | |
| exportStarHelper, | ||
| classPrivateFieldGetHelper, | ||
| classPrivateFieldSetHelper, | ||
| classPrivateMethodGetHelper, | ||
| classPrivateReadonlyHelper, | ||
| classPrivateWriteonlyHelper, | ||
| classPrivateAccessorGetHelper, | ||
| classPrivateAccessorSetHelper, | ||
| createBindingHelper, | ||
| setModuleDefaultHelper | ||
| ], helper => helper.name)); | ||
|
|
@@ -897,4 +1140,4 @@ namespace ts { | |
| && (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName) | ||
| && firstSegment.expression.escapedText === helperName; | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ugh we need to workshop this one a bit more.