Skip to content

Commit fbd749c

Browse files
Merge remote-tracking branch 'remotes/bloomberg/es-private-static-fields-methods-and-accessors' into es-private-methods-and-accessors
2 parents d8136f7 + 027bdb3 commit fbd749c

File tree

151 files changed

+9559
-1158
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

151 files changed

+9559
-1158
lines changed

package-lock.json

+637-637
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/compiler/checker.ts

+33-17
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ namespace ts {
240240
SetAccessor = 2,
241241
PropertyAssignment = 4,
242242
Method = 8,
243+
PrivateStatic = 16,
243244
GetOrSetAccessor = GetAccessor | SetAccessor,
244245
PropertyAssignmentOrMethod = PropertyAssignment | Method,
245246
}
@@ -32531,29 +32532,32 @@ namespace ts {
3253132532
const isStatic = hasSyntacticModifier(member, ModifierFlags.Static);
3253232533
const name = member.name;
3253332534
if (!name) {
32534-
return;
32535+
continue;
3253532536
}
32537+
const isPrivate = isPrivateIdentifier(name);
32538+
const privateStaticFlags = isPrivate && isStatic ? DeclarationMeaning.PrivateStatic : 0;
3253632539
const names =
32537-
isPrivateIdentifier(name) ? privateIdentifiers :
32540+
isPrivate ? privateIdentifiers :
3253832541
isStatic ? staticNames :
3253932542
instanceNames;
32543+
3254032544
const memberName = name && getPropertyNameForPropertyNameNode(name);
3254132545
if (memberName) {
3254232546
switch (member.kind) {
3254332547
case SyntaxKind.GetAccessor:
32544-
addName(names, name, memberName, DeclarationMeaning.GetAccessor);
32548+
addName(names, name, memberName, DeclarationMeaning.GetAccessor | privateStaticFlags);
3254532549
break;
3254632550

3254732551
case SyntaxKind.SetAccessor:
32548-
addName(names, name, memberName, DeclarationMeaning.SetAccessor);
32552+
addName(names, name, memberName, DeclarationMeaning.SetAccessor | privateStaticFlags);
3254932553
break;
3255032554

3255132555
case SyntaxKind.PropertyDeclaration:
32552-
addName(names, name, memberName, DeclarationMeaning.GetOrSetAccessor);
32556+
addName(names, name, memberName, DeclarationMeaning.GetOrSetAccessor | privateStaticFlags);
3255332557
break;
3255432558

3255532559
case SyntaxKind.MethodDeclaration:
32556-
addName(names, name, memberName, DeclarationMeaning.Method);
32560+
addName(names, name, memberName, DeclarationMeaning.Method | privateStaticFlags);
3255732561
break;
3255832562
}
3255932563
}
@@ -32563,16 +32567,25 @@ namespace ts {
3256332567
function addName(names: UnderscoreEscapedMap<DeclarationMeaning>, location: Node, name: __String, meaning: DeclarationMeaning) {
3256432568
const prev = names.get(name);
3256532569
if (prev) {
32566-
if (prev & DeclarationMeaning.Method) {
32567-
if (meaning !== DeclarationMeaning.Method) {
32568-
error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location));
32569-
}
32570-
}
32571-
else if (prev & meaning) {
32572-
error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location));
32570+
// For private identifiers, do not allow mixing of static and instance members with the same name
32571+
if ((prev & DeclarationMeaning.PrivateStatic) !== (meaning & DeclarationMeaning.PrivateStatic)) {
32572+
error(location, Diagnostics.Duplicate_identifier_0_Static_and_instance_elements_cannot_share_the_same_private_name, getTextOfNode(location));
3257332573
}
3257432574
else {
32575-
names.set(name, prev | meaning);
32575+
const prevIsMethod = !!(prev & DeclarationMeaning.Method);
32576+
const isMethod = !!(meaning & DeclarationMeaning.Method);
32577+
if (prevIsMethod || isMethod) {
32578+
if (prevIsMethod !== isMethod) {
32579+
error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location));
32580+
}
32581+
// If this is a method/method duplication is might be an overload, so this will be handled when overloads are considered
32582+
}
32583+
else if (prev & meaning & ~DeclarationMeaning.PrivateStatic) {
32584+
error(location, Diagnostics.Duplicate_identifier_0, getTextOfNode(location));
32585+
}
32586+
else {
32587+
names.set(name, prev | meaning);
32588+
}
3257632589
}
3257732590
}
3257832591
else {
@@ -32691,6 +32704,9 @@ namespace ts {
3269132704
checkVariableLikeDeclaration(node);
3269232705

3269332706
setNodeLinksForPrivateIdentifierScope(node);
32707+
if (isPrivateIdentifier(node.name) && hasStaticModifier(node) && node.initializer && languageVersion === ScriptTarget.ESNext && !compilerOptions.useDefineForClassFields) {
32708+
error(node.initializer, Diagnostics.Static_fields_with_private_names_can_t_have_initializers_when_the_useDefineForClassFields_flag_is_not_specified_with_a_target_of_esnext_Consider_adding_the_useDefineForClassFields_flag);
32709+
}
3269432710
}
3269532711

3269632712
function checkPropertySignature(node: PropertySignature) {
@@ -36461,6 +36477,9 @@ namespace ts {
3646136477
}
3646236478

3646336479
function checkClassDeclaration(node: ClassDeclaration) {
36480+
if (some(node.decorators) && some(node.members, p => hasStaticModifier(p) && isPrivateIdentifierClassElementDeclaration(p))) {
36481+
grammarErrorOnNode(node.decorators[0], Diagnostics.Class_decorators_can_t_be_used_with_static_private_identifier_Consider_removing_the_experimental_decorator);
36482+
}
3646436483
if (!node.name && !hasSyntacticModifier(node, ModifierFlags.Default)) {
3646536484
grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
3646636485
}
@@ -40024,9 +40043,6 @@ namespace ts {
4002440043
else if (flags & ModifierFlags.Abstract) {
4002540044
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_1_modifier, "static", "abstract");
4002640045
}
40027-
else if (isPrivateIdentifierClassElementDeclaration(node)) {
40028-
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_with_a_private_identifier, "static");
40029-
}
4003040046
flags |= ModifierFlags.Static;
4003140047
lastStatic = modifier;
4003240048
break;

src/compiler/diagnosticMessages.json

+13-1
Original file line numberDiff line numberDiff line change
@@ -3284,11 +3284,19 @@
32843284
"category": "Error",
32853285
"code": 2802
32863286
},
3287-
32883287
"Cannot assign to private method '{0}'. Private methods are not writable.": {
32893288
"category": "Error",
32903289
"code": 2803
32913290
},
3291+
"Duplicate identifier '{0}'. Static and instance elements cannot share the same private name.": {
3292+
"category": "Error",
3293+
"code": 2804
3294+
},
3295+
"Static fields with private names can't have initializers when the '--useDefineForClassFields' flag is not specified with a '--target' of 'esnext'. Consider adding the '--useDefineForClassFields' flag.": {
3296+
"category": "Error",
3297+
"code": 2805
3298+
},
3299+
32923300
"Import declaration '{0}' is using private name '{1}'.": {
32933301
"category": "Error",
32943302
"code": 4000
@@ -6381,5 +6389,9 @@
63816389
"Invalid value for 'jsxFragmentFactory'. '{0}' is not a valid identifier or qualified-name.": {
63826390
"category": "Error",
63836391
"code": 18035
6392+
},
6393+
"Class decorators can't be used with static private identifier. Consider removing the experimental decorator.": {
6394+
"category": "Error",
6395+
"code": 18036
63846396
}
63856397
}

src/compiler/factory/emitHelpers.ts

+143
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ namespace ts {
3939
createClassPrivateWriteonlyHelper(receiver: Expression): Expression;
4040
createClassPrivateAccessorGetHelper(receiver: Expression, instances: Identifier, fn: Identifier): Expression;
4141
createClassPrivateAccessorSetHelper(receiver: Expression, instances: Identifier, fn: Identifier, value: Expression): Expression;
42+
// Class Static Private Helpers
43+
createClassStaticPrivateFieldGetHelper(receiver: Expression, classConstructor: Identifier, privateField: Identifier): Expression;
44+
createClassStaticPrivateFieldSetHelper(receiver: Expression, classConstructor: Identifier, privateField: Identifier, value: Expression): Expression;
45+
createClassStaticPrivateMethodGetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier): Expression;
46+
createClassStaticPrivateReadonlyHelper(receiver: Expression, value: Expression): Expression;
47+
createClassStaticPrivateWriteonlyHelper(receiver: Expression): Expression;
48+
createClassStaticPrivateAccessorGetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier): Expression;
49+
createClassStaticPrivateAccessorSetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier, value: Expression): Expression;
4250
}
4351

4452
export function createEmitHelperFactory(context: TransformationContext): EmitHelperFactory {
@@ -82,6 +90,13 @@ namespace ts {
8290
createClassPrivateWriteonlyHelper,
8391
createClassPrivateAccessorGetHelper,
8492
createClassPrivateAccessorSetHelper,
93+
createClassStaticPrivateFieldGetHelper,
94+
createClassStaticPrivateFieldSetHelper,
95+
createClassStaticPrivateMethodGetHelper,
96+
createClassStaticPrivateReadonlyHelper,
97+
createClassStaticPrivateWriteonlyHelper,
98+
createClassStaticPrivateAccessorGetHelper,
99+
createClassStaticPrivateAccessorSetHelper,
85100
};
86101

87102
/**
@@ -412,6 +427,41 @@ namespace ts {
412427
context.requestEmitHelper(classPrivateAccessorSetHelper);
413428
return factory.createCallExpression(getUnscopedHelperName("__classPrivateAccessorSet"), /*typeArguments*/ undefined, [receiver, instances, fn, value]);
414429
}
430+
// Class Private Static Helpers
431+
function createClassStaticPrivateFieldGetHelper(receiver: Expression, classConstructor: Identifier, privateField: Identifier) {
432+
context.requestEmitHelper(classStaticPrivateFieldGetHelper);
433+
return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateFieldGet"), /*typeArguments*/ undefined, [receiver, classConstructor, privateField]);
434+
}
435+
436+
function createClassStaticPrivateFieldSetHelper(receiver: Expression, classConstructor: Identifier, privateField: Identifier, value: Expression) {
437+
context.requestEmitHelper(classStaticPrivateFieldSetHelper);
438+
return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateFieldSet"), /*typeArguments*/ undefined, [receiver, classConstructor, privateField, value]);
439+
}
440+
441+
function createClassStaticPrivateMethodGetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier) {
442+
context.requestEmitHelper(classStaticPrivateMethodGetHelper);
443+
return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateMethodGet"), /*typeArguments*/ undefined, [receiver, classConstructor, fn]);
444+
}
445+
446+
function createClassStaticPrivateReadonlyHelper(receiver: Expression, value: Expression) {
447+
context.requestEmitHelper(classStaticPrivateReadonlyHelper);
448+
return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateReadonly"), /*typeArguments*/ undefined, [receiver, value]);
449+
}
450+
451+
function createClassStaticPrivateWriteonlyHelper(receiver: Expression) {
452+
context.requestEmitHelper(classStaticPrivateWriteonlyHelper);
453+
return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateWriteonly"), /*typeArguments*/ undefined, [receiver]);
454+
}
455+
456+
function createClassStaticPrivateAccessorGetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier) {
457+
context.requestEmitHelper(classStaticPrivateAccessorGetHelper);
458+
return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateAccessorGet"), /*typeArguments*/ undefined, [receiver, classConstructor, fn]);
459+
}
460+
461+
function createClassStaticPrivateAccessorSetHelper(receiver: Expression, classConstructor: Identifier, fn: Identifier, value: Expression) {
462+
context.requestEmitHelper(classStaticPrivateAccessorSetHelper);
463+
return factory.createCallExpression(getUnscopedHelperName("__classStaticPrivateAccessorSet"), /*typeArguments*/ undefined, [receiver, classConstructor, fn, value]);
464+
}
415465
}
416466

417467
/* @internal */
@@ -939,6 +989,99 @@ namespace ts {
939989
};`
940990
};
941991

992+
export const classStaticPrivateFieldGetHelper: UnscopedEmitHelper = {
993+
name: "typescript:classStaticPrivateFieldGet",
994+
importName: "__classStaticPrivateFieldGet",
995+
scoped: false,
996+
text: `
997+
var __classStaticPrivateFieldGet = (this && this.__classStaticPrivateFieldGet) || function (receiver, classConstructor, propertyDescriptor) {
998+
if (receiver !== classConstructor) {
999+
throw new TypeError("Private static access of wrong provenance");
1000+
}
1001+
if (propertyDescriptor === undefined) {
1002+
throw new TypeError("Private static field was accessed before its declaration.");
1003+
}
1004+
return propertyDescriptor.value;
1005+
};`
1006+
};
1007+
1008+
export const classStaticPrivateFieldSetHelper: UnscopedEmitHelper = {
1009+
name: "typescript:classStaticPrivateFieldSet",
1010+
importName: "__classStaticPrivateFieldSet",
1011+
scoped: false,
1012+
text: `
1013+
var __classStaticPrivateFieldSet = (this && this.__classStaticPrivateFieldSet) || function (receiver, classConstructor, propertyDescriptor, value) {
1014+
if (receiver !== classConstructor) {
1015+
throw new TypeError("Private static access of wrong provenance");
1016+
}
1017+
if (propertyDescriptor === undefined) {
1018+
throw new TypeError("Private static field was accessed before its declaration.");
1019+
}
1020+
propertyDescriptor.value = value;
1021+
return value;
1022+
};`
1023+
};
1024+
1025+
export const classStaticPrivateMethodGetHelper: UnscopedEmitHelper = {
1026+
name: "typescript:classStaticPrivateMethodGet",
1027+
importName: "__classStaticPrivateMethodGet",
1028+
scoped: false,
1029+
text: `
1030+
var __classStaticPrivateMethodGet = (this && this.__classStaticPrivateMethodGet) || function (receiver, classConstructor, fn) {
1031+
if (receiver !== classConstructor) {
1032+
throw new TypeError("Private static access of wrong provenance");
1033+
}
1034+
return fn;
1035+
};`
1036+
};
1037+
1038+
export const classStaticPrivateReadonlyHelper: UnscopedEmitHelper = {
1039+
name: "typescript:classStaticPrivateReadonly",
1040+
importName: "__classStaticPrivateReadonly",
1041+
scoped: false,
1042+
text: `
1043+
var __classStaticPrivateReadonly = (this && this.__classStaticPrivateReadonly) || function () {
1044+
throw new TypeError("Private static element is not writable");
1045+
};`
1046+
};
1047+
1048+
export const classStaticPrivateWriteonlyHelper: UnscopedEmitHelper = {
1049+
name: "typescript:classStaticPrivateWriteonly",
1050+
importName: "__classStaticPrivateWriteonly",
1051+
scoped: false,
1052+
text: `
1053+
var __classStaticPrivateWriteonly = (this && this.__classStaticPrivateWriteonly) || function () {
1054+
throw new TypeError("Private static element is not readable");
1055+
};`
1056+
};
1057+
1058+
export const classStaticPrivateAccessorGetHelper: UnscopedEmitHelper = {
1059+
name: "typescript:classStaticPrivateAccessorGet",
1060+
importName: "__classStaticPrivateAccessorGet",
1061+
scoped: false,
1062+
text: `
1063+
var __classStaticPrivateAccessorGet = (this && this.__classStaticPrivateAccessorGet) || function (receiver, classConstructor, fn) {
1064+
if (receiver !== classConstructor) {
1065+
throw new TypeError("Private static access of wrong provenance");
1066+
}
1067+
return fn.call(receiver);
1068+
};`
1069+
};
1070+
1071+
export const classStaticPrivateAccessorSetHelper: UnscopedEmitHelper = {
1072+
name: "typescript:classStaticPrivateAccessorSet",
1073+
importName: "__classStaticPrivateAccessorSet",
1074+
scoped: false,
1075+
text: `
1076+
var __classStaticPrivateAccessorSet = (this && this.__classStaticPrivateAccessorSet) || function (receiver, classConstructor, fn, value) {
1077+
if (receiver !== classConstructor) {
1078+
throw new TypeError("Private static access of wrong provenance");
1079+
}
1080+
fn.call(receiver, value);
1081+
return value;
1082+
};`
1083+
};
1084+
9421085
let allUnscopedEmitHelpers: ReadonlyESMap<string, UnscopedEmitHelper> | undefined;
9431086

9441087
export function getAllUnscopedEmitHelpers() {

0 commit comments

Comments
 (0)