@@ -376,8 +376,8 @@ namespace ts {
376
376
const moduleAugmentation = <ModuleDeclaration>moduleName.parent;
377
377
if (moduleAugmentation.symbol.valueDeclaration !== moduleAugmentation) {
378
378
// this is a combined symbol for multiple augmentations within the same file.
379
- // its symbol already has accumulated information for all declarations
380
- // so we need to add it just once - do the work only for first declaration
379
+ // its symbol already has accumulated information for all declarations
380
+ // so we need to add it just once - do the work only for first declaration
381
381
Debug.assert(moduleAugmentation.symbol.declarations.length > 1);
382
382
return;
383
383
}
@@ -386,7 +386,7 @@ namespace ts {
386
386
mergeSymbolTable(globals, moduleAugmentation.symbol.exports);
387
387
}
388
388
else {
389
- // find a module that about to be augmented
389
+ // find a module that about to be augmented
390
390
let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found);
391
391
if (!mainModule) {
392
392
return;
@@ -810,7 +810,7 @@ namespace ts {
810
810
}
811
811
812
812
// No static member is present.
813
- // Check if we're in an instance method and look for a relevant instance member.
813
+ // Check if we're in an instance method and look for a relevant instance member.
814
814
if (location === container && !(location.flags & NodeFlags.Static)) {
815
815
const instanceType = (<InterfaceType>getDeclaredTypeOfSymbol(classSymbol)).thisType;
816
816
if (getPropertyOfType(instanceType, name)) {
@@ -1161,7 +1161,7 @@ namespace ts {
1161
1161
return getMergedSymbol(sourceFile.symbol);
1162
1162
}
1163
1163
if (moduleNotFoundError) {
1164
- // report errors only if it was requested
1164
+ // report errors only if it was requested
1165
1165
error(moduleReferenceLiteral, Diagnostics.File_0_is_not_a_module, sourceFile.fileName);
1166
1166
}
1167
1167
return undefined;
@@ -7115,14 +7115,10 @@ namespace ts {
7115
7115
return false;
7116
7116
}
7117
7117
7118
- function isSuperPropertyAccess(node: Node) {
7119
- return node.kind === SyntaxKind.PropertyAccessExpression
7120
- && (<PropertyAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
7121
- }
7122
-
7123
- function isSuperElementAccess(node: Node) {
7124
- return node.kind === SyntaxKind.ElementAccessExpression
7125
- && (<ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
7118
+ function isSuperPropertyOrElementAccess(node: Node) {
7119
+ return (node.kind === SyntaxKind.PropertyAccessExpression
7120
+ || node.kind === SyntaxKind.ElementAccessExpression)
7121
+ && (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
7126
7122
}
7127
7123
7128
7124
function checkSuperExpression(node: Node): Type {
@@ -7177,8 +7173,63 @@ namespace ts {
7177
7173
getNodeLinks(node).flags |= nodeCheckFlag;
7178
7174
7179
7175
// Due to how we emit async functions, we need to specialize the emit for an async method that contains a `super` reference.
7176
+ // This is due to the fact that we emit the body of an async function inside of a generator function. As generator
7177
+ // functions cannot reference `super`, we emit a helper inside of the method body, but outside of the generator. This helper
7178
+ // uses an arrow function, which is permitted to reference `super`.
7179
+ //
7180
+ // There are two primary ways we can access `super` from within an async method. The first is getting the value of a property
7181
+ // or indexed access on super, either as part of a right-hand-side expression or call expression. The second is when setting the value
7182
+ // of a property or indexed access, either as part of an assignment expression or destructuring assignment.
7183
+ //
7184
+ // The simplest case is reading a value, in which case we will emit something like the following:
7185
+ //
7186
+ // // ts
7187
+ // ...
7188
+ // async asyncMethod() {
7189
+ // let x = await super.asyncMethod();
7190
+ // return x;
7191
+ // }
7192
+ // ...
7193
+ //
7194
+ // // js
7195
+ // ...
7196
+ // asyncMethod() {
7197
+ // const _super = name => super[name];
7198
+ // return __awaiter(this, arguments, Promise, function *() {
7199
+ // let x = yield _super("asyncMethod").call(this);
7200
+ // return x;
7201
+ // });
7202
+ // }
7203
+ // ...
7204
+ //
7205
+ // The more complex case is when we wish to assign a value, especially as part of a destructuring assignment. As both cases
7206
+ // are legal in ES6, but also likely less frequent, we emit the same more complex helper for both scenarios:
7207
+ //
7208
+ // // ts
7209
+ // ...
7210
+ // async asyncMethod(ar: Promise<any[]>) {
7211
+ // [super.a, super.b] = await ar;
7212
+ // }
7213
+ // ...
7214
+ //
7215
+ // // js
7216
+ // ...
7217
+ // asyncMethod(ar) {
7218
+ // const _super = (function (geti, seti) {
7219
+ // const cache = Object.create(null);
7220
+ // return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
7221
+ // })(name => super[name], (name, value) => super[name] = value);
7222
+ // return __awaiter(this, arguments, Promise, function *() {
7223
+ // [_super("a").value, _super("b").value] = yield ar;
7224
+ // });
7225
+ // }
7226
+ // ...
7227
+ //
7228
+ // This helper creates an object with a "value" property that wraps the `super` property or indexed access for both get and set.
7229
+ // This is required for destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment
7230
+ // while a property access can.
7180
7231
if (container.kind === SyntaxKind.MethodDeclaration && container.flags & NodeFlags.Async) {
7181
- if ((isSuperPropertyAccess( node.parent) || isSuperElementAccess(node.parent) ) && isAssignmentTarget(node.parent)) {
7232
+ if (isSuperPropertyOrElementAccess( node.parent) && isAssignmentTarget(node.parent)) {
7182
7233
getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuperBinding;
7183
7234
}
7184
7235
else {
@@ -14224,10 +14275,10 @@ namespace ts {
14224
14275
if (isAmbientExternalModule) {
14225
14276
if (isExternalModuleAugmentation(node)) {
14226
14277
// body of the augmentation should be checked for consistency only if augmentation was applied to its target (either global scope or module)
14227
- // otherwise we'll be swamped in cascading errors.
14278
+ // otherwise we'll be swamped in cascading errors.
14228
14279
// We can detect if augmentation was applied using following rules:
14229
14280
// - augmentation for a global scope is always applied
14230
- // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module).
14281
+ // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module).
14231
14282
const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & SymbolFlags.Merged);
14232
14283
if (checkBody) {
14233
14284
// body of ambient external module is always a module block
0 commit comments