Skip to content

Commit f784d8a

Browse files
committed
Fixes for review comments.
* rename _super to _superIndex and _superProps to _super. * reinstate early exit for transformers by marking super accesses as esnext/es2017 in `binder.ts`. * adjust comment in `checker.ts` to new emit.
1 parent 8290a5a commit f784d8a

File tree

7 files changed

+70
-57
lines changed

7 files changed

+70
-57
lines changed

src/compiler/binder.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3442,7 +3442,9 @@ namespace ts {
34423442
// ES6 syntax, and requires a lexical `this` binding.
34433443
if (transformFlags & TransformFlags.Super) {
34443444
transformFlags ^= TransformFlags.Super;
3445-
transformFlags |= TransformFlags.ContainsSuper;
3445+
// super inside of an async function requires hoisting the super access (ES2017).
3446+
// same for super inside of an async generator, which is ESNext.
3447+
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
34463448
}
34473449

34483450
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@@ -3458,7 +3460,9 @@ namespace ts {
34583460
// ES6 syntax, and requires a lexical `this` binding.
34593461
if (expressionFlags & TransformFlags.Super) {
34603462
transformFlags &= ~TransformFlags.Super;
3461-
transformFlags |= TransformFlags.ContainsSuper;
3463+
// super inside of an async function requires hoisting the super access (ES2017).
3464+
// same for super inside of an async generator, which is ESNext.
3465+
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
34623466
}
34633467

34643468
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;

src/compiler/checker.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15735,16 +15735,18 @@ namespace ts {
1573515735
// // js
1573615736
// ...
1573715737
// asyncMethod() {
15738-
// const _super_asyncMethod = name => super.asyncMethod;
15738+
// const _super = Object.create(null, {
15739+
// asyncMethod: { get: () => super.asyncMethod },
15740+
// });
1573915741
// return __awaiter(this, arguments, Promise, function *() {
15740-
// let x = yield _super_asyncMethod.call(this);
15742+
// let x = yield _super.asyncMethod.call(this);
1574115743
// return x;
1574215744
// });
1574315745
// }
1574415746
// ...
1574515747
//
1574615748
// The more complex case is when we wish to assign a value, especially as part of a destructuring assignment. As both cases
15747-
// are legal in ES6, but also likely less frequent, we emit the same more complex helper for both scenarios:
15749+
// are legal in ES6, but also likely less frequent, we only emit setters if there is an assignment:
1574815750
//
1574915751
// // ts
1575015752
// ...
@@ -15756,17 +15758,18 @@ namespace ts {
1575615758
// // js
1575715759
// ...
1575815760
// asyncMethod(ar) {
15759-
// const _super_a = {get value() { return super.a; }, set value(v) { super.a = v; }};
15760-
// const _super_b = {get value() { return super.b; }, set value(v) { super.b = v; }};
15761+
// const _super = Object.create(null, {
15762+
// a: { get: () => super.a, set: (v) => super.a = v },
15763+
// b: { get: () => super.b, set: (v) => super.b = v }
15764+
// };
1576115765
// return __awaiter(this, arguments, Promise, function *() {
15762-
// [_super_a.value, _super_b.value] = yield ar;
15766+
// [_super.a, _super.b] = yield ar;
1576315767
// });
1576415768
// }
1576515769
// ...
1576615770
//
15767-
// This helper creates an object with a "value" property that wraps the `super` property for both get and set. This is required for
15768-
// destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment while a property
15769-
// access can.
15771+
// Creating an object that has getter and setters instead of just an accessor funtion is required for destructuring assignments
15772+
// as a call expression cannot be used as the target of a destructuring assignment while a property access can.
1577015773
//
1577115774
// For element access expressions (`super[x]`), we emit a generic helper that forwards the element access in both situations.
1577215775
if (container.kind === SyntaxKind.MethodDeclaration && hasModifier(container, ModifierFlags.Async)) {

src/compiler/transformers/es2017.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ namespace ts {
6262
}
6363

6464
function visitor(node: Node): VisitResult<Node> {
65+
if ((node.transformFlags & TransformFlags.ContainsES2017) === 0) {
66+
return node;
67+
}
6568
switch (node.kind) {
6669
case SyntaxKind.AsyncKeyword:
6770
// ES2017 async modifier should be elided for targets < ES2017
@@ -553,7 +556,7 @@ namespace ts {
553556
// Disable substitution in the generated super accessor itself.
554557
else if (enabledSubstitutions && substitutedSuperAccessors[getNodeId(node)]) {
555558
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
556-
enclosingSuperContainerFlags = 0 as NodeCheckFlags;
559+
enclosingSuperContainerFlags = 0;
557560
previousOnEmitNode(hint, node, emitCallback);
558561
enclosingSuperContainerFlags = savedEnclosingSuperContainerFlags;
559562
return;
@@ -592,7 +595,7 @@ namespace ts {
592595
if (node.expression.kind === SyntaxKind.SuperKeyword) {
593596
return setTextRange(
594597
createPropertyAccess(
595-
createFileLevelUniqueName("_superProps"),
598+
createFileLevelUniqueName("_super"),
596599
node.name),
597600
node
598601
);
@@ -642,7 +645,7 @@ namespace ts {
642645
return setTextRange(
643646
createPropertyAccess(
644647
createCall(
645-
createFileLevelUniqueName("_super"),
648+
createFileLevelUniqueName("_superIndex"),
646649
/*typeArguments*/ undefined,
647650
[argumentExpression]
648651
),
@@ -654,7 +657,7 @@ namespace ts {
654657
else {
655658
return setTextRange(
656659
createCall(
657-
createFileLevelUniqueName("_super"),
660+
createFileLevelUniqueName("_superIndex"),
658661
/*typeArguments*/ undefined,
659662
[argumentExpression]
660663
),
@@ -729,7 +732,7 @@ namespace ts {
729732
createVariableDeclarationList(
730733
[
731734
createVariableDeclaration(
732-
createFileLevelUniqueName("_superProps"),
735+
createFileLevelUniqueName("_super"),
733736
/* type */ undefined,
734737
createCall(
735738
createPropertyAccess(
@@ -794,14 +797,14 @@ namespace ts {
794797
name: "typescript:async-super",
795798
scoped: true,
796799
text: helperString`
797-
const ${"_super"} = name => super[name];`
800+
const ${"_superIndex"} = name => super[name];`
798801
};
799802

800803
export const advancedAsyncSuperHelper: EmitHelper = {
801804
name: "typescript:advanced-async-super",
802805
scoped: true,
803806
text: helperString`
804-
const ${"_super"} = (function (geti, seti) {
807+
const ${"_superIndex"} = (function (geti, seti) {
805808
const cache = Object.create(null);
806809
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
807810
})(name => super[name], (name, value) => super[name] = value);`

src/compiler/transformers/esnext.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ namespace ts {
6161
}
6262

6363
function visitorWorker(node: Node, noDestructuringValue: boolean): VisitResult<Node> {
64+
if ((node.transformFlags & TransformFlags.ContainsESNext) === 0) {
65+
return node;
66+
}
6467
switch (node.kind) {
6568
case SyntaxKind.AwaitExpression:
6669
return visitAwaitExpression(node as AwaitExpression);
@@ -854,7 +857,7 @@ namespace ts {
854857
if (node.expression.kind === SyntaxKind.SuperKeyword) {
855858
return setTextRange(
856859
createPropertyAccess(
857-
createFileLevelUniqueName("_superProps"),
860+
createFileLevelUniqueName("_super"),
858861
node.name),
859862
node
860863
);
@@ -904,7 +907,7 @@ namespace ts {
904907
return setTextRange(
905908
createPropertyAccess(
906909
createCall(
907-
createIdentifier("_super"),
910+
createIdentifier("_superIndex"),
908911
/*typeArguments*/ undefined,
909912
[argumentExpression]
910913
),
@@ -916,7 +919,7 @@ namespace ts {
916919
else {
917920
return setTextRange(
918921
createCall(
919-
createIdentifier("_super"),
922+
createIdentifier("_superIndex"),
920923
/*typeArguments*/ undefined,
921924
[argumentExpression]
922925
),

tests/baselines/reference/asyncMethodWithSuperConflict_es6.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -77,55 +77,55 @@ class A {
7777
class B extends A {
7878
// async method with only call/get on 'super' does not require a binding
7979
simple() {
80-
const _super_1 = name => super[name];
81-
const _superProps_1 = Object.create(null, {
80+
const _superIndex = name => super[name];
81+
const _super_1 = Object.create(null, {
8282
x: { get: () => super.x },
8383
y: { get: () => super.y }
8484
});
8585
return __awaiter(this, void 0, void 0, function* () {
8686
const _super = null;
8787
const _superProps = null;
8888
// call with property access
89-
_superProps_1.x.call(this);
89+
_super_1.x.call(this);
9090
// call additional property.
91-
_superProps_1.y.call(this);
91+
_super_1.y.call(this);
9292
// call with element access
93-
_super_1("x").call(this);
93+
_superIndex("x").call(this);
9494
// property access (read)
95-
const a = _superProps_1.x;
95+
const a = _super_1.x;
9696
// element access (read)
97-
const b = _super_1("x");
97+
const b = _superIndex("x");
9898
});
9999
}
100100
// async method with assignment/destructuring on 'super' requires a binding
101101
advanced() {
102-
const _super_1 = (function (geti, seti) {
102+
const _superIndex = (function (geti, seti) {
103103
const cache = Object.create(null);
104104
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
105105
})(name => super[name], (name, value) => super[name] = value);
106-
const _superProps_1 = Object.create(null, {
106+
const _super_1 = Object.create(null, {
107107
x: { get: () => super.x, set: v => super.x = v }
108108
});
109109
return __awaiter(this, void 0, void 0, function* () {
110110
const _super = null;
111111
const _superProps = null;
112112
const f = () => { };
113113
// call with property access
114-
_superProps_1.x.call(this);
114+
_super_1.x.call(this);
115115
// call with element access
116-
_super_1("x").value.call(this);
116+
_superIndex("x").value.call(this);
117117
// property access (read)
118-
const a = _superProps_1.x;
118+
const a = _super_1.x;
119119
// element access (read)
120-
const b = _super_1("x").value;
120+
const b = _superIndex("x").value;
121121
// property access (assign)
122-
_superProps_1.x = f;
122+
_super_1.x = f;
123123
// element access (assign)
124-
_super_1("x").value = f;
124+
_superIndex("x").value = f;
125125
// destructuring assign with property access
126-
({ f: _superProps_1.x } = { f });
126+
({ f: _super_1.x } = { f });
127127
// destructuring assign with element access
128-
({ f: _super_1("x").value } = { f });
128+
({ f: _superIndex("x").value } = { f });
129129
});
130130
}
131131
}

tests/baselines/reference/asyncMethodWithSuper_es6.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,51 +65,51 @@ class A {
6565
class B extends A {
6666
// async method with only call/get on 'super' does not require a binding
6767
simple() {
68-
const _super = name => super[name];
69-
const _superProps = Object.create(null, {
68+
const _superIndex = name => super[name];
69+
const _super = Object.create(null, {
7070
x: { get: () => super.x },
7171
y: { get: () => super.y }
7272
});
7373
return __awaiter(this, void 0, void 0, function* () {
7474
// call with property access
75-
_superProps.x.call(this);
75+
_super.x.call(this);
7676
// call additional property.
77-
_superProps.y.call(this);
77+
_super.y.call(this);
7878
// call with element access
79-
_super("x").call(this);
79+
_superIndex("x").call(this);
8080
// property access (read)
81-
const a = _superProps.x;
81+
const a = _super.x;
8282
// element access (read)
83-
const b = _super("x");
83+
const b = _superIndex("x");
8484
});
8585
}
8686
// async method with assignment/destructuring on 'super' requires a binding
8787
advanced() {
88-
const _super = (function (geti, seti) {
88+
const _superIndex = (function (geti, seti) {
8989
const cache = Object.create(null);
9090
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
9191
})(name => super[name], (name, value) => super[name] = value);
92-
const _superProps = Object.create(null, {
92+
const _super = Object.create(null, {
9393
x: { get: () => super.x, set: v => super.x = v }
9494
});
9595
return __awaiter(this, void 0, void 0, function* () {
9696
const f = () => { };
9797
// call with property access
98-
_superProps.x.call(this);
98+
_super.x.call(this);
9999
// call with element access
100-
_super("x").value.call(this);
100+
_superIndex("x").value.call(this);
101101
// property access (read)
102-
const a = _superProps.x;
102+
const a = _super.x;
103103
// element access (read)
104-
const b = _super("x").value;
104+
const b = _superIndex("x").value;
105105
// property access (assign)
106-
_superProps.x = f;
106+
_super.x = f;
107107
// element access (assign)
108-
_super("x").value = f;
108+
_superIndex("x").value = f;
109109
// destructuring assign with property access
110-
({ f: _superProps.x } = { f });
110+
({ f: _super.x } = { f });
111111
// destructuring assign with element access
112-
({ f: _super("x").value } = { f });
112+
({ f: _superIndex("x").value } = { f });
113113
});
114114
}
115115
}

tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,11 @@ class B9 {
263263
}
264264
class C9 extends B9 {
265265
f() {
266-
const _superProps = Object.create(null, {
266+
const _super = Object.create(null, {
267267
g: { get: () => super.g }
268268
});
269269
return __asyncGenerator(this, arguments, function* f_1() {
270-
_superProps.g.call(this);
270+
_super.g.call(this);
271271
});
272272
}
273273
}

0 commit comments

Comments
 (0)