Skip to content

Commit e618d75

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 f0826cf commit e618d75

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
@@ -3445,7 +3445,9 @@ namespace ts {
34453445
// ES6 syntax, and requires a lexical `this` binding.
34463446
if (transformFlags & TransformFlags.Super) {
34473447
transformFlags ^= TransformFlags.Super;
3448-
transformFlags |= TransformFlags.ContainsSuper;
3448+
// super inside of an async function requires hoisting the super access (ES2017).
3449+
// same for super inside of an async generator, which is ESNext.
3450+
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
34493451
}
34503452

34513453
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
@@ -3461,7 +3463,9 @@ namespace ts {
34613463
// ES6 syntax, and requires a lexical `this` binding.
34623464
if (expressionFlags & TransformFlags.Super) {
34633465
transformFlags &= ~TransformFlags.Super;
3464-
transformFlags |= TransformFlags.ContainsSuper;
3466+
// super inside of an async function requires hoisting the super access (ES2017).
3467+
// same for super inside of an async generator, which is ESNext.
3468+
transformFlags |= TransformFlags.ContainsSuper | TransformFlags.ContainsES2017 | TransformFlags.ContainsESNext;
34653469
}
34663470

34673471
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;

src/compiler/checker.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16180,16 +16180,18 @@ namespace ts {
1618016180
// // js
1618116181
// ...
1618216182
// asyncMethod() {
16183-
// const _super_asyncMethod = name => super.asyncMethod;
16183+
// const _super = Object.create(null, {
16184+
// asyncMethod: { get: () => super.asyncMethod },
16185+
// });
1618416186
// return __awaiter(this, arguments, Promise, function *() {
16185-
// let x = yield _super_asyncMethod.call(this);
16187+
// let x = yield _super.asyncMethod.call(this);
1618616188
// return x;
1618716189
// });
1618816190
// }
1618916191
// ...
1619016192
//
1619116193
// The more complex case is when we wish to assign a value, especially as part of a destructuring assignment. As both cases
16192-
// are legal in ES6, but also likely less frequent, we emit the same more complex helper for both scenarios:
16194+
// are legal in ES6, but also likely less frequent, we only emit setters if there is an assignment:
1619316195
//
1619416196
// // ts
1619516197
// ...
@@ -16201,17 +16203,18 @@ namespace ts {
1620116203
// // js
1620216204
// ...
1620316205
// asyncMethod(ar) {
16204-
// const _super_a = {get value() { return super.a; }, set value(v) { super.a = v; }};
16205-
// const _super_b = {get value() { return super.b; }, set value(v) { super.b = v; }};
16206+
// const _super = Object.create(null, {
16207+
// a: { get: () => super.a, set: (v) => super.a = v },
16208+
// b: { get: () => super.b, set: (v) => super.b = v }
16209+
// };
1620616210
// return __awaiter(this, arguments, Promise, function *() {
16207-
// [_super_a.value, _super_b.value] = yield ar;
16211+
// [_super.a, _super.b] = yield ar;
1620816212
// });
1620916213
// }
1621016214
// ...
1621116215
//
16212-
// This helper creates an object with a "value" property that wraps the `super` property for both get and set. This is required for
16213-
// destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment while a property
16214-
// access can.
16216+
// Creating an object that has getter and setters instead of just an accessor funtion is required for destructuring assignments
16217+
// as a call expression cannot be used as the target of a destructuring assignment while a property access can.
1621516218
//
1621616219
// For element access expressions (`super[x]`), we emit a generic helper that forwards the element access in both situations.
1621716220
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)