Skip to content

Commit 8bfc540

Browse files
authored
Merge pull request #15 from joeywatts/esnext-private-instance-fields
Transform private named instance fields
2 parents 979155c + fa17cdf commit 8bfc540

40 files changed

+1568
-52
lines changed

src/compiler/binder.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3637,6 +3637,10 @@ namespace ts {
36373637
let excludeFlags = TransformFlags.NodeExcludes;
36383638

36393639
switch (kind) {
3640+
case SyntaxKind.PrivateName:
3641+
// Private names are ESNext syntax.
3642+
transformFlags |= TransformFlags.AssertESNext;
3643+
break;
36403644
case SyntaxKind.AsyncKeyword:
36413645
case SyntaxKind.AwaitExpression:
36423646
// async/await is ES2017 syntax, but may be ESNext syntax (for async generators)

src/compiler/transformers/esnext.ts

Lines changed: 394 additions & 18 deletions
Large diffs are not rendered by default.

src/compiler/transformers/generators.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -667,28 +667,6 @@ namespace ts {
667667
}
668668
}
669669

670-
function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator {
671-
return kind >= SyntaxKind.FirstCompoundAssignment
672-
&& kind <= SyntaxKind.LastCompoundAssignment;
673-
}
674-
675-
function getOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher {
676-
switch (kind) {
677-
case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken;
678-
case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken;
679-
case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken;
680-
case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken;
681-
case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken;
682-
case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken;
683-
case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken;
684-
case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken;
685-
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
686-
case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken;
687-
case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken;
688-
case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken;
689-
}
690-
}
691-
692670
/**
693671
* Visits a right-associative binary expression containing `yield`.
694672
*

src/compiler/transformers/ts.ts

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -929,17 +929,12 @@ namespace ts {
929929
const parameters = transformConstructorParameters(constructor);
930930
const body = transformConstructorBody(node.members, constructor, parametersWithPropertyAssignments);
931931
members.push(startOnNewLine(
932-
setOriginalNode(
933-
setTextRange(
934-
createConstructor(
935-
/*decorators*/ undefined,
936-
/*modifiers*/ undefined,
937-
parameters,
938-
body
939-
),
940-
constructor
941-
),
942-
constructor
932+
updateConstructor(
933+
constructor,
934+
/*decorators*/ undefined,
935+
/*modifiers*/ undefined,
936+
parameters,
937+
body
943938
)
944939
));
945940
addRange(

src/compiler/transformers/utilities.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,26 @@ namespace ts {
335335
return member.kind === SyntaxKind.PropertyDeclaration
336336
&& (<PropertyDeclaration>member).initializer !== undefined;
337337
}
338+
339+
export function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator {
340+
return kind >= SyntaxKind.FirstCompoundAssignment
341+
&& kind <= SyntaxKind.LastCompoundAssignment;
342+
}
343+
344+
export function getOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher {
345+
switch (kind) {
346+
case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken;
347+
case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken;
348+
case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken;
349+
case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken;
350+
case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken;
351+
case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken;
352+
case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken;
353+
case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken;
354+
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
355+
case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken;
356+
case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken;
357+
case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken;
358+
}
359+
}
338360
}

src/compiler/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,11 @@ namespace ts {
942942
initializer?: Expression; // Optional initializer
943943
}
944944

945+
/*@internal*/
946+
export interface PrivateNamedPropertyDeclaration extends PropertyDeclaration {
947+
name: PrivateName;
948+
}
949+
945950
export interface ObjectLiteralElement extends NamedDeclaration {
946951
_objectLiteralBrandBrand: any;
947952
name?: PropertyName;
@@ -1752,6 +1757,11 @@ namespace ts {
17521757
name: Identifier | PrivateName;
17531758
}
17541759

1760+
/*@internal*/
1761+
export interface PrivateNamedPropertyAccessExpression extends PropertyAccessExpression {
1762+
name: PrivateName;
1763+
}
1764+
17551765
export interface SuperPropertyAccessExpression extends PropertyAccessExpression {
17561766
expression: SuperExpression;
17571767
}

src/compiler/utilities.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6111,6 +6111,16 @@ namespace ts {
61116111
|| kind === SyntaxKind.ComputedPropertyName;
61126112
}
61136113

6114+
/*@internal*/
6115+
export function isPrivateNamedPropertyDeclaration(node: Node): node is PrivateNamedPropertyDeclaration {
6116+
return isPropertyDeclaration(node) && isPrivateName(node.name);
6117+
}
6118+
6119+
/*@internal*/
6120+
export function isPrivateNamedPropertyAccessExpression(node: Node): node is PrivateNamedPropertyAccessExpression {
6121+
return isPropertyAccessExpression(node) && isPrivateName(node.name);
6122+
}
6123+
61146124
export function isBindingName(node: Node): node is BindingName {
61156125
const kind = node.kind;
61166126
return kind === SyntaxKind.Identifier

tests/baselines/reference/privateNameField.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ class A {
77
}
88

99
//// [privateNameField.js]
10+
var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; };
11+
var _name;
1012
var A = /** @class */ (function () {
1113
function A(name) {
12-
this.#name = name;
14+
_name.set(this, void 0);
15+
_classPrivateFieldSet(this, _name, name);
1316
}
1417
return A;
1518
}());
19+
_name = new WeakMap();
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//// [privateNameFieldAccess.ts]
2+
class A {
3+
#myField = "hello world";
4+
constructor() {
5+
console.log(this.#myField);
6+
}
7+
}
8+
9+
10+
//// [privateNameFieldAccess.js]
11+
var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); };
12+
var _myField;
13+
var A = /** @class */ (function () {
14+
function A() {
15+
_myField.set(this, "hello world");
16+
console.log(_classPrivateFieldGet(this, _myField));
17+
}
18+
return A;
19+
}());
20+
_myField = new WeakMap();
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts ===
2+
class A {
3+
>A : Symbol(A, Decl(privateNameFieldAccess.ts, 0, 0))
4+
5+
#myField = "hello world";
6+
>#myField : Symbol(A.#myField, Decl(privateNameFieldAccess.ts, 0, 9))
7+
8+
constructor() {
9+
console.log(this.#myField);
10+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
11+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
12+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
13+
>this.#myField : Symbol(A.#myField, Decl(privateNameFieldAccess.ts, 0, 9))
14+
>this : Symbol(A, Decl(privateNameFieldAccess.ts, 0, 0))
15+
}
16+
}
17+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/conformance/classes/members/privateNames/privateNameFieldAccess.ts ===
2+
class A {
3+
>A : A
4+
5+
#myField = "hello world";
6+
>#myField : string
7+
>"hello world" : "hello world"
8+
9+
constructor() {
10+
console.log(this.#myField);
11+
>console.log(this.#myField) : void
12+
>console.log : (message?: any, ...optionalParams: any[]) => void
13+
>console : Console
14+
>log : (message?: any, ...optionalParams: any[]) => void
15+
>this.#myField : string
16+
>this : this
17+
}
18+
}
19+
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//// [privateNameFieldAssignment.ts]
2+
class A {
3+
#field = 0;
4+
constructor() {
5+
this.#field = 1;
6+
this.#field += 2;
7+
this.#field -= 3;
8+
this.#field /= 4;
9+
this.#field *= 5;
10+
this.#field **= 6;
11+
this.#field %= 7;
12+
this.#field <<= 8;
13+
this.#field >>= 9;
14+
this.#field >>>= 10;
15+
this.#field &= 11;
16+
this.#field |= 12;
17+
this.#field ^= 13;
18+
A.getInstance().#field = 1;
19+
A.getInstance().#field += 2;
20+
A.getInstance().#field -= 3;
21+
A.getInstance().#field /= 4;
22+
A.getInstance().#field *= 5;
23+
A.getInstance().#field **= 6;
24+
A.getInstance().#field %= 7;
25+
A.getInstance().#field <<= 8;
26+
A.getInstance().#field >>= 9;
27+
A.getInstance().#field >>>= 10;
28+
A.getInstance().#field &= 11;
29+
A.getInstance().#field |= 12;
30+
A.getInstance().#field ^= 13;
31+
}
32+
static getInstance() {
33+
return new A();
34+
}
35+
}
36+
37+
38+
//// [privateNameFieldAssignment.js]
39+
var _classPrivateFieldSet = function (receiver, privateMap, value) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to set private field on non-instance"); } privateMap.set(receiver, value); return value; };
40+
var _classPrivateFieldGet = function (receiver, privateMap) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return privateMap.get(receiver); };
41+
var _field;
42+
var A = /** @class */ (function () {
43+
function A() {
44+
_field.set(this, 0);
45+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
46+
_classPrivateFieldSet(this, _field, 1);
47+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) + 2);
48+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) - 3);
49+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) / 4);
50+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) * 5);
51+
_classPrivateFieldSet(this, _field, Math.pow(_classPrivateFieldGet(this, _field), 6));
52+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) % 7);
53+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) << 8);
54+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) >> 9);
55+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) >>> 10);
56+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) & 11);
57+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) | 12);
58+
_classPrivateFieldSet(this, _field, _classPrivateFieldGet(this, _field) ^ 13);
59+
_classPrivateFieldSet(A.getInstance(), _field, 1);
60+
_classPrivateFieldSet(_a = A.getInstance(), _field, _classPrivateFieldGet(_a, _field) + 2);
61+
_classPrivateFieldSet(_b = A.getInstance(), _field, _classPrivateFieldGet(_b, _field) - 3);
62+
_classPrivateFieldSet(_c = A.getInstance(), _field, _classPrivateFieldGet(_c, _field) / 4);
63+
_classPrivateFieldSet(_d = A.getInstance(), _field, _classPrivateFieldGet(_d, _field) * 5);
64+
_classPrivateFieldSet(_e = A.getInstance(), _field, Math.pow(_classPrivateFieldGet(_e, _field), 6));
65+
_classPrivateFieldSet(_f = A.getInstance(), _field, _classPrivateFieldGet(_f, _field) % 7);
66+
_classPrivateFieldSet(_g = A.getInstance(), _field, _classPrivateFieldGet(_g, _field) << 8);
67+
_classPrivateFieldSet(_h = A.getInstance(), _field, _classPrivateFieldGet(_h, _field) >> 9);
68+
_classPrivateFieldSet(_j = A.getInstance(), _field, _classPrivateFieldGet(_j, _field) >>> 10);
69+
_classPrivateFieldSet(_k = A.getInstance(), _field, _classPrivateFieldGet(_k, _field) & 11);
70+
_classPrivateFieldSet(_l = A.getInstance(), _field, _classPrivateFieldGet(_l, _field) | 12);
71+
_classPrivateFieldSet(_m = A.getInstance(), _field, _classPrivateFieldGet(_m, _field) ^ 13);
72+
}
73+
A.getInstance = function () {
74+
return new A();
75+
};
76+
return A;
77+
}());
78+
_field = new WeakMap();

0 commit comments

Comments
 (0)