Skip to content

Commit a9cb10e

Browse files
joeywattsJoey Watts
authored and
Joey Watts
committed
Add private named instance field transformation (#31)
Implements private instance fields on top of the class properties refactor. Signed-off-by: Joseph Watts <[email protected]> Signed-off-by: Max Heiber <[email protected]>
1 parent afa2ac6 commit a9cb10e

File tree

57 files changed

+1739
-112
lines changed

Some content is hidden

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

57 files changed

+1739
-112
lines changed

src/compiler/binder.ts

+4
Original file line numberDiff line numberDiff line change
@@ -3878,6 +3878,10 @@ namespace ts {
38783878
case SyntaxKind.BreakStatement:
38793879
transformFlags |= TransformFlags.ContainsHoistedDeclarationOrCompletion;
38803880
break;
3881+
3882+
case SyntaxKind.PrivateName:
3883+
transformFlags |= TransformFlags.ContainsClassFields;
3884+
break;
38813885
}
38823886

38833887
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;

src/compiler/transformers/classFields.ts

+431-24
Large diffs are not rendered by default.

src/compiler/transformers/generators.ts

-22
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/utilities.ts

+22
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,28 @@ namespace ts {
250250
isWellKnownSymbolSyntactically(expression);
251251
}
252252

253+
export function isCompoundAssignment(kind: BinaryOperator): kind is CompoundAssignmentOperator {
254+
return kind >= SyntaxKind.FirstCompoundAssignment
255+
&& kind <= SyntaxKind.LastCompoundAssignment;
256+
}
257+
258+
export function getOperatorForCompoundAssignment(kind: CompoundAssignmentOperator): BitwiseOperatorOrHigher {
259+
switch (kind) {
260+
case SyntaxKind.PlusEqualsToken: return SyntaxKind.PlusToken;
261+
case SyntaxKind.MinusEqualsToken: return SyntaxKind.MinusToken;
262+
case SyntaxKind.AsteriskEqualsToken: return SyntaxKind.AsteriskToken;
263+
case SyntaxKind.AsteriskAsteriskEqualsToken: return SyntaxKind.AsteriskAsteriskToken;
264+
case SyntaxKind.SlashEqualsToken: return SyntaxKind.SlashToken;
265+
case SyntaxKind.PercentEqualsToken: return SyntaxKind.PercentToken;
266+
case SyntaxKind.LessThanLessThanEqualsToken: return SyntaxKind.LessThanLessThanToken;
267+
case SyntaxKind.GreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanToken;
268+
case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: return SyntaxKind.GreaterThanGreaterThanGreaterThanToken;
269+
case SyntaxKind.AmpersandEqualsToken: return SyntaxKind.AmpersandToken;
270+
case SyntaxKind.BarEqualsToken: return SyntaxKind.BarToken;
271+
case SyntaxKind.CaretEqualsToken: return SyntaxKind.CaretToken;
272+
}
273+
}
274+
253275
/**
254276
* Adds super call and preceding prologue directives into the list of statements.
255277
*

src/compiler/types.ts

+10
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,11 @@ namespace ts {
953953
initializer?: Expression; // Optional initializer
954954
}
955955

956+
/*@internal*/
957+
export interface PrivateNamedPropertyDeclaration extends PropertyDeclaration {
958+
name: PrivateName;
959+
}
960+
956961
export interface ObjectLiteralElement extends NamedDeclaration {
957962
_objectLiteralBrand: any;
958963
name?: PropertyName;
@@ -1777,6 +1782,11 @@ namespace ts {
17771782
name: Identifier | PrivateName;
17781783
}
17791784

1785+
/*@internal*/
1786+
export interface PrivateNamedPropertyAccessExpression extends PropertyAccessExpression {
1787+
name: PrivateName;
1788+
}
1789+
17801790
export interface SuperPropertyAccessExpression extends PropertyAccessExpression {
17811791
expression: SuperExpression;
17821792
}

src/compiler/utilities.ts

+10
Original file line numberDiff line numberDiff line change
@@ -6294,6 +6294,16 @@ namespace ts {
62946294
|| kind === SyntaxKind.ArrayBindingPattern;
62956295
}
62966296

6297+
/*@internal*/
6298+
export function isPrivateNamedPropertyDeclaration(node: Node): node is PrivateNamedPropertyDeclaration {
6299+
return isPropertyDeclaration(node) && isPrivateName(node.name);
6300+
}
6301+
6302+
/*@internal*/
6303+
export function isPrivateNamedPropertyAccessExpression(node: Node): node is PrivateNamedPropertyAccessExpression {
6304+
return isPropertyAccessExpression(node) && isPrivateName(node.name);
6305+
}
6306+
62976307
// Functions
62986308

62996309
export function isFunctionLike(node: Node): node is SignatureDeclaration {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//// [privateNameDeclaration.ts]
2+
class A {
3+
#name: string;
4+
}
5+
6+
7+
//// [privateNameDeclaration.js]
8+
var _name;
9+
var A = /** @class */ (function () {
10+
function A() {
11+
_name.set(this, void 0);
12+
}
13+
return A;
14+
}());
15+
_name = new WeakMap();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=== tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts ===
2+
class A {
3+
>A : Symbol(A, Decl(privateNameDeclaration.ts, 0, 0))
4+
5+
#name: string;
6+
>#name : Symbol(A.#name, Decl(privateNameDeclaration.ts, 0, 9))
7+
}
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=== tests/cases/conformance/classes/members/privateNames/privateNameDeclaration.ts ===
2+
class A {
3+
>A : A
4+
5+
#name: string;
6+
>#name : string
7+
}
8+

tests/baselines/reference/privateNameDuplicateField.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ class A {
88

99

1010
//// [privateNameDuplicateField.js]
11-
"use strict";
1211
// @target es6
12+
var _foo, _foo_1;
13+
"use strict";
1314
var A = /** @class */ (function () {
1415
function A() {
15-
this.#foo = "foo";
16-
this.#foo = "foo";
16+
_foo_1.set(this, "foo");
17+
_foo_1.set(this, "foo");
1718
}
1819
return A;
1920
}());
21+
_foo = new WeakMap(), _foo_1 = new WeakMap();

tests/baselines/reference/privateNameField.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ class A {
99
}
1010

1111
//// [privateNameField.js]
12-
"use strict";
1312
// @target es6
13+
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; };
14+
var _name;
15+
"use strict";
1416
var A = /** @class */ (function () {
1517
function A(name) {
16-
this.#name = name;
18+
_name.set(this, void 0);
19+
_classPrivateFieldSet(this, _name, name);
1720
}
1821
return A;
1922
}());
23+
_name = new WeakMap();
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();
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+
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+
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+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
45+
_field.set(this, 0);
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)