Skip to content

Commit 7a5326e

Browse files
author
Max Heiber
committed
simplify and fixes for private methods emit
Signed-off-by: Max Heiber <mheiber@bloomberg.net>
1 parent ab3a3b1 commit 7a5326e

File tree

5 files changed

+100
-39
lines changed

5 files changed

+100
-39
lines changed

src/compiler/transformers/esnext.ts

Lines changed: 29 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -414,17 +414,8 @@ namespace ts {
414414
const containsPropertyInitializer = forEach(node.members, isInitializedProperty);
415415
let body = constructor ? constructor.body : undefined;
416416
let parameters = constructor ? constructor.parameters : undefined;
417-
const shouldTransformConstructorBody = containsPropertyInitializer || declaresPrivateNames;
418-
if (shouldTransformConstructorBody) {
419-
if (containsPropertyInitializer) {
420-
parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context);
421-
}
422-
else {
423-
// provide a scope for hoisted declarations for WeakSet or WeakMap for private name brand checks
424-
// not needed if `visitParameterList` was called, because that starts/suspends the lexical environment
425-
context.startLexicalEnvironment();
426-
context.suspendLexicalEnvironment();
427-
}
417+
if (containsPropertyInitializer || declaresPrivateNames) {
418+
parameters = visitParameterList(constructor ? constructor.parameters : undefined, visitor, context);
428419
body = transformConstructorBody(node, constructor, isDerivedClass, declaresPrivateNames);
429420
}
430421
if (!body) {
@@ -486,22 +477,11 @@ namespace ts {
486477
indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor);
487478
}
488479

489-
// Add the property initializers. Transforms this:
490-
//
491-
// public x = 1;
492-
//
493-
// Into this:
494-
//
495-
// constructor() {
496-
// this.x = 1;
497-
// }
498-
//
499-
addInitializedPropertyStatements(statements, properties, createThis());
500480
if (classDeclaresPrivateNames) {
501481
last(privateNameEnvironmentStack).forEach(({ placement, accumulator }) => {
502482
switch (placement) {
503483
case PrivateNamePlacement.InstanceField:
504-
// TODO: instance field add accumulator
484+
// handled in addInitializedPropertyStatements
505485
break;
506486
case PrivateNamePlacement.InstanceMethod:
507487
statements.push(
@@ -517,6 +497,17 @@ namespace ts {
517497
}
518498
});
519499
}
500+
// Add the property initializers. Transforms this:
501+
//
502+
// public x = 1;
503+
//
504+
// Into this:
505+
//
506+
// constructor() {
507+
// this.x = 1;
508+
// }
509+
//
510+
addInitializedPropertyStatements(statements, properties, createThis());
520511

521512
// Add existing statements, skipping the initial super call.
522513
if (constructor) {
@@ -705,21 +696,18 @@ namespace ts {
705696
function visitPropertyAccessExpression(node: PropertyAccessExpression) {
706697
if (isPrivateName(node.name)) {
707698
const privateNameInfo = accessPrivateName(node.name);
708-
if (privateNameInfo) {
709-
switch (privateNameInfo.placement) {
710-
case PrivateNamePlacement.InstanceField:
711-
return setOriginalNode(
712-
setTextRange(
713-
createClassPrivateFieldGetHelper(
714-
context,
715-
visitNode(node.expression, visitor, isExpression),
716-
privateNameInfo.accumulator
717-
),
718-
node
719-
),
720-
node
721-
);
722-
}
699+
if (privateNameInfo && privateNameInfo.placement === PrivateNamePlacement.InstanceField) {
700+
return setOriginalNode(
701+
setTextRange(
702+
createClassPrivateFieldGetHelper(
703+
context,
704+
visitNode(node.expression, visitor, isExpression),
705+
privateNameInfo.accumulator
706+
),
707+
node
708+
),
709+
node
710+
);
723711
}
724712
}
725713
return visitEachChild(node, visitor, context);
@@ -808,7 +796,9 @@ namespace ts {
808796
);
809797
receiver = generatedName;
810798
}
811-
const privateNameEntry = last(privateNameEnvironmentStack).get(node.expression.name.escapedText);
799+
const privateNameEntry = privateNameEnvironmentStack.length
800+
? last(privateNameEnvironmentStack).get(node.expression.name.escapedText)
801+
: undefined;
812802
if (privateNameEntry && privateNameEntry.placement === PrivateNamePlacement.InstanceMethod) {
813803
return setOriginalNode(
814804
setTextRange(
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [privateNamedMemberOrder.ts]
2+
class A {
3+
#foo: () => 1;
4+
#bar() {
5+
return this.#foo;
6+
}
7+
baz = this.#bar();
8+
}
9+
10+
//// [privateNamedMemberOrder.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 _classPrivateNamedCallCheck = function (receiver, privateSet) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get weak field on non-instance"); }};
13+
var _fooPrivate, _barPrivate, _bar;
14+
var A = /** @class */ (function () {
15+
function A() {
16+
_barPrivate.add(this);
17+
_fooPrivate.set(this, void 0);
18+
this.baz = _bar.call(this);
19+
}
20+
return A;
21+
}());
22+
_fooPrivate = new WeakMap(), _barPrivate = new WeakSet(), _bar = function _bar() {
23+
_classPrivateNamedCallCheck(this, _barPrivate);
24+
return _classPrivateFieldGet(this, _fooPrivate);
25+
};
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/privateNamedMemberOrder.ts ===
2+
class A {
3+
>A : Symbol(A, Decl(privateNamedMemberOrder.ts, 0, 0))
4+
5+
#foo: () => 1;
6+
>#foo : Symbol(A.#foo, Decl(privateNamedMemberOrder.ts, 0, 9))
7+
8+
#bar() {
9+
>#bar : Symbol(A.#bar, Decl(privateNamedMemberOrder.ts, 1, 18))
10+
11+
return this.#foo;
12+
>this.#foo : Symbol(A.#foo, Decl(privateNamedMemberOrder.ts, 0, 9))
13+
>this : Symbol(A, Decl(privateNamedMemberOrder.ts, 0, 0))
14+
}
15+
baz = this.#bar();
16+
>baz : Symbol(A.baz, Decl(privateNamedMemberOrder.ts, 4, 5))
17+
>this.#bar : Symbol(A.#bar, Decl(privateNamedMemberOrder.ts, 1, 18))
18+
>this : Symbol(A, Decl(privateNamedMemberOrder.ts, 0, 0))
19+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
=== tests/cases/conformance/classes/members/privateNames/privateNamedMemberOrder.ts ===
2+
class A {
3+
>A : A
4+
5+
#foo: () => 1;
6+
>#foo : () => 1
7+
8+
#bar() {
9+
>#bar : () => () => 1
10+
11+
return this.#foo;
12+
>this.#foo : () => 1
13+
>this : this
14+
}
15+
baz = this.#bar();
16+
>baz : () => 1
17+
>this.#bar() : () => 1
18+
>this.#bar : () => () => 1
19+
>this : this
20+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class A {
2+
#foo: () => 1;
3+
#bar() {
4+
return this.#foo;
5+
}
6+
baz = this.#bar();
7+
}

0 commit comments

Comments
 (0)