Merge pull request #5870 from Microsoft/alternateFixSuperInAsyncMethod
Fix super in async method
This commit is contained in:
commit
2b1fd8c419
17 changed files with 538 additions and 42 deletions
|
@ -376,8 +376,8 @@ namespace ts {
|
|||
const moduleAugmentation = <ModuleDeclaration>moduleName.parent;
|
||||
if (moduleAugmentation.symbol.valueDeclaration !== moduleAugmentation) {
|
||||
// this is a combined symbol for multiple augmentations within the same file.
|
||||
// its symbol already has accumulated information for all declarations
|
||||
// so we need to add it just once - do the work only for first declaration
|
||||
// its symbol already has accumulated information for all declarations
|
||||
// so we need to add it just once - do the work only for first declaration
|
||||
Debug.assert(moduleAugmentation.symbol.declarations.length > 1);
|
||||
return;
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ namespace ts {
|
|||
mergeSymbolTable(globals, moduleAugmentation.symbol.exports);
|
||||
}
|
||||
else {
|
||||
// find a module that about to be augmented
|
||||
// find a module that about to be augmented
|
||||
let mainModule = resolveExternalModuleNameWorker(moduleName, moduleName, Diagnostics.Invalid_module_name_in_augmentation_module_0_cannot_be_found);
|
||||
if (!mainModule) {
|
||||
return;
|
||||
|
@ -812,7 +812,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
// No static member is present.
|
||||
// Check if we're in an instance method and look for a relevant instance member.
|
||||
// Check if we're in an instance method and look for a relevant instance member.
|
||||
if (location === container && !(location.flags & NodeFlags.Static)) {
|
||||
const instanceType = (<InterfaceType>getDeclaredTypeOfSymbol(classSymbol)).thisType;
|
||||
if (getPropertyOfType(instanceType, name)) {
|
||||
|
@ -1163,7 +1163,7 @@ namespace ts {
|
|||
return getMergedSymbol(sourceFile.symbol);
|
||||
}
|
||||
if (moduleNotFoundError) {
|
||||
// report errors only if it was requested
|
||||
// report errors only if it was requested
|
||||
error(moduleReferenceLiteral, Diagnostics.File_0_is_not_a_module, sourceFile.fileName);
|
||||
}
|
||||
return undefined;
|
||||
|
@ -7147,7 +7147,6 @@ namespace ts {
|
|||
|
||||
if (node.parserContextFlags & ParserContextFlags.Await) {
|
||||
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
|
||||
getNodeLinks(node).flags |= NodeCheckFlags.LexicalArguments;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7379,6 +7378,71 @@ namespace ts {
|
|||
|
||||
getNodeLinks(node).flags |= nodeCheckFlag;
|
||||
|
||||
// Due to how we emit async functions, we need to specialize the emit for an async method that contains a `super` reference.
|
||||
// This is due to the fact that we emit the body of an async function inside of a generator function. As generator
|
||||
// functions cannot reference `super`, we emit a helper inside of the method body, but outside of the generator. This helper
|
||||
// uses an arrow function, which is permitted to reference `super`.
|
||||
//
|
||||
// There are two primary ways we can access `super` from within an async method. The first is getting the value of a property
|
||||
// or indexed access on super, either as part of a right-hand-side expression or call expression. The second is when setting the value
|
||||
// of a property or indexed access, either as part of an assignment expression or destructuring assignment.
|
||||
//
|
||||
// The simplest case is reading a value, in which case we will emit something like the following:
|
||||
//
|
||||
// // ts
|
||||
// ...
|
||||
// async asyncMethod() {
|
||||
// let x = await super.asyncMethod();
|
||||
// return x;
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// // js
|
||||
// ...
|
||||
// asyncMethod() {
|
||||
// const _super = name => super[name];
|
||||
// return __awaiter(this, arguments, Promise, function *() {
|
||||
// let x = yield _super("asyncMethod").call(this);
|
||||
// return x;
|
||||
// });
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// The more complex case is when we wish to assign a value, especially as part of a destructuring assignment. As both cases
|
||||
// are legal in ES6, but also likely less frequent, we emit the same more complex helper for both scenarios:
|
||||
//
|
||||
// // ts
|
||||
// ...
|
||||
// async asyncMethod(ar: Promise<any[]>) {
|
||||
// [super.a, super.b] = await ar;
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// // js
|
||||
// ...
|
||||
// asyncMethod(ar) {
|
||||
// const _super = (function (geti, seti) {
|
||||
// const cache = Object.create(null);
|
||||
// return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
// })(name => super[name], (name, value) => super[name] = value);
|
||||
// return __awaiter(this, arguments, Promise, function *() {
|
||||
// [_super("a").value, _super("b").value] = yield ar;
|
||||
// });
|
||||
// }
|
||||
// ...
|
||||
//
|
||||
// This helper creates an object with a "value" property that wraps the `super` property or indexed access for both get and set.
|
||||
// This is required for destructuring assignments, as a call expression cannot be used as the target of a destructuring assignment
|
||||
// while a property access can.
|
||||
if (container.kind === SyntaxKind.MethodDeclaration && container.flags & NodeFlags.Async) {
|
||||
if (isSuperPropertyOrElementAccess(node.parent) && isAssignmentTarget(node.parent)) {
|
||||
getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuperBinding;
|
||||
}
|
||||
else {
|
||||
getNodeLinks(container).flags |= NodeCheckFlags.AsyncMethodWithSuper;
|
||||
}
|
||||
}
|
||||
|
||||
if (needToCaptureLexicalThis) {
|
||||
// call expressions are allowed only in constructors so they should always capture correct 'this'
|
||||
// super property access expressions can also appear in arrow functions -
|
||||
|
@ -14426,10 +14490,10 @@ namespace ts {
|
|||
if (isAmbientExternalModule) {
|
||||
if (isExternalModuleAugmentation(node)) {
|
||||
// body of the augmentation should be checked for consistency only if augmentation was applied to its target (either global scope or module)
|
||||
// otherwise we'll be swamped in cascading errors.
|
||||
// otherwise we'll be swamped in cascading errors.
|
||||
// We can detect if augmentation was applied using following rules:
|
||||
// - augmentation for a global scope is always applied
|
||||
// - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module).
|
||||
// - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module).
|
||||
const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & SymbolFlags.Merged);
|
||||
if (checkBody) {
|
||||
// body of ambient external module is always a module block
|
||||
|
|
|
@ -324,7 +324,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.call(thisArg, _arguments)).next());
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};`;
|
||||
|
||||
|
@ -1488,11 +1488,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
}
|
||||
|
||||
function emitExpressionIdentifier(node: Identifier) {
|
||||
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.LexicalArguments) {
|
||||
write("_arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
const container = resolver.getReferencedExportContainer(node);
|
||||
if (container) {
|
||||
if (container.kind === SyntaxKind.SourceFile) {
|
||||
|
@ -2122,6 +2117,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
return;
|
||||
}
|
||||
|
||||
if (languageVersion === ScriptTarget.ES6 &&
|
||||
node.expression.kind === SyntaxKind.SuperKeyword &&
|
||||
isInAsyncMethodWithSuperInES6(node)) {
|
||||
const name = <StringLiteral>createSynthesizedNode(SyntaxKind.StringLiteral);
|
||||
name.text = node.name.text;
|
||||
emitSuperAccessInAsyncMethod(node.expression, name);
|
||||
return;
|
||||
}
|
||||
|
||||
emit(node.expression);
|
||||
const indentedBeforeDot = indentIfOnDifferentLines(node, node.expression, node.dotToken);
|
||||
|
||||
|
@ -2207,6 +2211,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
if (tryEmitConstantValue(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (languageVersion === ScriptTarget.ES6 &&
|
||||
node.expression.kind === SyntaxKind.SuperKeyword &&
|
||||
isInAsyncMethodWithSuperInES6(node)) {
|
||||
emitSuperAccessInAsyncMethod(node.expression, node.argumentExpression);
|
||||
return;
|
||||
}
|
||||
|
||||
emit(node.expression);
|
||||
write("[");
|
||||
emit(node.argumentExpression);
|
||||
|
@ -2282,23 +2294,47 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
write(")");
|
||||
}
|
||||
|
||||
function isInAsyncMethodWithSuperInES6(node: Node) {
|
||||
if (languageVersion === ScriptTarget.ES6) {
|
||||
const container = getSuperContainer(node, /*includeFunctions*/ false);
|
||||
if (container && resolver.getNodeCheckFlags(container) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function emitSuperAccessInAsyncMethod(superNode: Node, argumentExpression: Expression) {
|
||||
const container = getSuperContainer(superNode, /*includeFunctions*/ false);
|
||||
const isSuperBinding = resolver.getNodeCheckFlags(container) & NodeCheckFlags.AsyncMethodWithSuperBinding;
|
||||
write("_super(");
|
||||
emit(argumentExpression);
|
||||
write(isSuperBinding ? ").value" : ")");
|
||||
}
|
||||
|
||||
function emitCallExpression(node: CallExpression) {
|
||||
if (languageVersion < ScriptTarget.ES6 && hasSpreadElement(node.arguments)) {
|
||||
emitCallWithSpread(node);
|
||||
return;
|
||||
}
|
||||
|
||||
const expression = node.expression;
|
||||
let superCall = false;
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
emitSuper(node.expression);
|
||||
let isAsyncMethodWithSuper = false;
|
||||
if (expression.kind === SyntaxKind.SuperKeyword) {
|
||||
emitSuper(expression);
|
||||
superCall = true;
|
||||
}
|
||||
else {
|
||||
emit(node.expression);
|
||||
superCall = node.expression.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.expression).expression.kind === SyntaxKind.SuperKeyword;
|
||||
superCall = isSuperPropertyOrElementAccess(expression);
|
||||
isAsyncMethodWithSuper = superCall && isInAsyncMethodWithSuperInES6(node);
|
||||
emit(expression);
|
||||
}
|
||||
if (superCall && languageVersion < ScriptTarget.ES6) {
|
||||
|
||||
if (superCall && (languageVersion < ScriptTarget.ES6 || isAsyncMethodWithSuper)) {
|
||||
write(".call(");
|
||||
emitThis(node.expression);
|
||||
emitThis(expression);
|
||||
if (node.arguments.length) {
|
||||
write(", ");
|
||||
emitCommaList(node.arguments);
|
||||
|
@ -4470,6 +4506,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
write(" {");
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
|
||||
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
|
||||
writeLines(`
|
||||
const _super = (function (geti, seti) {
|
||||
const cache = Object.create(null);
|
||||
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
})(name => super[name], (name, value) => super[name] = value);`);
|
||||
writeLine();
|
||||
}
|
||||
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
|
||||
write(`const _super = name => super[name];`);
|
||||
writeLine();
|
||||
}
|
||||
|
||||
write("return");
|
||||
}
|
||||
|
||||
|
@ -4489,12 +4539,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
}
|
||||
|
||||
// Emit the call to __awaiter.
|
||||
if (hasLexicalArguments) {
|
||||
write(", function* (_arguments)");
|
||||
}
|
||||
else {
|
||||
write(", function* ()");
|
||||
}
|
||||
write(", function* ()");
|
||||
|
||||
// Emit the signature and body for the inner generator function.
|
||||
emitFunctionBody(node);
|
||||
|
|
|
@ -2058,14 +2058,15 @@ namespace ts {
|
|||
SuperInstance = 0x00000100, // Instance 'super' reference
|
||||
SuperStatic = 0x00000200, // Static 'super' reference
|
||||
ContextChecked = 0x00000400, // Contextual types have been assigned
|
||||
LexicalArguments = 0x00000800,
|
||||
CaptureArguments = 0x00001000, // Lexical 'arguments' used in body (for async functions)
|
||||
AsyncMethodWithSuper = 0x00000800, // An async method that reads a value from a member of 'super'.
|
||||
AsyncMethodWithSuperBinding = 0x00001000, // An async method that assigns a value to a member of 'super'.
|
||||
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body (for async functions)
|
||||
|
||||
// Values for enum members have been computed, and any errors have been reported for them.
|
||||
EnumValuesComputed = 0x00002000,
|
||||
BlockScopedBindingInLoop = 0x00004000,
|
||||
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
|
||||
LoopWithBlockScopedBindingCapturedInFunction = 0x00010000, // Loop that contains block scoped variable captured in closure
|
||||
EnumValuesComputed = 0x00004000,
|
||||
BlockScopedBindingInLoop = 0x00008000,
|
||||
LexicalModuleMergesWithClass = 0x00010000, // Instantiated lexical module declaration is merged with a previous class declaration.
|
||||
LoopWithBlockScopedBindingCapturedInFunction = 0x00020000, // Loop that contains block scoped variable captured in closure
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
|
|
@ -850,6 +850,16 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a node is a property or element access expression for super.
|
||||
*/
|
||||
export function isSuperPropertyOrElementAccess(node: Node) {
|
||||
return (node.kind === SyntaxKind.PropertyAccessExpression
|
||||
|| node.kind === SyntaxKind.ElementAccessExpression)
|
||||
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
|
||||
|
||||
export function getEntityNameFromTypeNode(node: TypeNode): EntityName | Expression {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
|
|
|
@ -11,6 +11,6 @@ class C {
|
|||
class C {
|
||||
method() {
|
||||
function other() { }
|
||||
var fn = () => __awaiter(this, arguments, Promise, function* (_arguments) { return yield other.apply(this, _arguments); });
|
||||
var fn = () => __awaiter(this, arguments, Promise, function* () { return yield other.apply(this, arguments); });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.call(thisArg, _arguments)).next());
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function f0() {
|
||||
|
|
|
@ -45,7 +45,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.call(thisArg, _arguments)).next());
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function f0() {
|
||||
|
|
|
@ -21,7 +21,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.call(thisArg, _arguments)).next());
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
import { a } from './a';
|
||||
|
@ -36,7 +36,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.call(thisArg, _arguments)).next());
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
import { b } from './b';
|
||||
|
|
|
@ -21,7 +21,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.call(thisArg, _arguments)).next());
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
const task_1 = require("./task");
|
||||
|
|
99
tests/baselines/reference/asyncMethodWithSuper_es6.js
Normal file
99
tests/baselines/reference/asyncMethodWithSuper_es6.js
Normal file
|
@ -0,0 +1,99 @@
|
|||
//// [asyncMethodWithSuper_es6.ts]
|
||||
class A {
|
||||
x() {
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
// async method with only call/get on 'super' does not require a binding
|
||||
async simple() {
|
||||
// call with property access
|
||||
super.x();
|
||||
|
||||
// call with element access
|
||||
super["x"]();
|
||||
|
||||
// property access (read)
|
||||
const a = super.x;
|
||||
|
||||
// element access (read)
|
||||
const b = super["x"];
|
||||
}
|
||||
|
||||
// async method with assignment/destructuring on 'super' requires a binding
|
||||
async advanced() {
|
||||
const f = () => {};
|
||||
|
||||
// call with property access
|
||||
super.x();
|
||||
|
||||
// call with element access
|
||||
super["x"]();
|
||||
|
||||
// property access (read)
|
||||
const a = super.x;
|
||||
|
||||
// element access (read)
|
||||
const b = super["x"];
|
||||
|
||||
// property access (assign)
|
||||
super.x = f;
|
||||
|
||||
// element access (assign)
|
||||
super["x"] = f;
|
||||
|
||||
// destructuring assign with property access
|
||||
({ f: super.x } = { f });
|
||||
|
||||
// destructuring assign with element access
|
||||
({ f: super["x"] } = { f });
|
||||
}
|
||||
}
|
||||
|
||||
//// [asyncMethodWithSuper_es6.js]
|
||||
class A {
|
||||
x() {
|
||||
}
|
||||
}
|
||||
class B extends A {
|
||||
// async method with only call/get on 'super' does not require a binding
|
||||
simple() {
|
||||
const _super = name => super[name];
|
||||
return __awaiter(this, void 0, Promise, function* () {
|
||||
// call with property access
|
||||
_super("x").call(this);
|
||||
// call with element access
|
||||
_super("x").call(this);
|
||||
// property access (read)
|
||||
const a = _super("x");
|
||||
// element access (read)
|
||||
const b = _super("x");
|
||||
});
|
||||
}
|
||||
// async method with assignment/destructuring on 'super' requires a binding
|
||||
advanced() {
|
||||
const _super = (function (geti, seti) {
|
||||
const cache = Object.create(null);
|
||||
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
|
||||
})(name => super[name], (name, value) => super[name] = value);
|
||||
return __awaiter(this, void 0, Promise, function* () {
|
||||
const f = () => { };
|
||||
// call with property access
|
||||
_super("x").value.call(this);
|
||||
// call with element access
|
||||
_super("x").value.call(this);
|
||||
// property access (read)
|
||||
const a = _super("x").value;
|
||||
// element access (read)
|
||||
const b = _super("x").value;
|
||||
// property access (assign)
|
||||
_super("x").value = f;
|
||||
// element access (assign)
|
||||
_super("x").value = f;
|
||||
// destructuring assign with property access
|
||||
({ f: _super("x").value } = { f });
|
||||
// destructuring assign with element access
|
||||
({ f: _super("x").value } = { f });
|
||||
});
|
||||
}
|
||||
}
|
102
tests/baselines/reference/asyncMethodWithSuper_es6.symbols
Normal file
102
tests/baselines/reference/asyncMethodWithSuper_es6.symbols
Normal file
|
@ -0,0 +1,102 @@
|
|||
=== tests/cases/conformance/async/es6/asyncMethodWithSuper_es6.ts ===
|
||||
class A {
|
||||
>A : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
|
||||
x() {
|
||||
>x : Symbol(x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
>B : Symbol(B, Decl(asyncMethodWithSuper_es6.ts, 3, 1))
|
||||
>A : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
|
||||
// async method with only call/get on 'super' does not require a binding
|
||||
async simple() {
|
||||
>simple : Symbol(simple, Decl(asyncMethodWithSuper_es6.ts, 5, 19))
|
||||
|
||||
// call with property access
|
||||
super.x();
|
||||
>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
|
||||
// call with element access
|
||||
super["x"]();
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
|
||||
// property access (read)
|
||||
const a = super.x;
|
||||
>a : Symbol(a, Decl(asyncMethodWithSuper_es6.ts, 15, 13))
|
||||
>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
|
||||
// element access (read)
|
||||
const b = super["x"];
|
||||
>b : Symbol(b, Decl(asyncMethodWithSuper_es6.ts, 18, 13))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
}
|
||||
|
||||
// async method with assignment/destructuring on 'super' requires a binding
|
||||
async advanced() {
|
||||
>advanced : Symbol(advanced, Decl(asyncMethodWithSuper_es6.ts, 19, 5))
|
||||
|
||||
const f = () => {};
|
||||
>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 23, 13))
|
||||
|
||||
// call with property access
|
||||
super.x();
|
||||
>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
|
||||
// call with element access
|
||||
super["x"]();
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
|
||||
// property access (read)
|
||||
const a = super.x;
|
||||
>a : Symbol(a, Decl(asyncMethodWithSuper_es6.ts, 32, 13))
|
||||
>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
|
||||
// element access (read)
|
||||
const b = super["x"];
|
||||
>b : Symbol(b, Decl(asyncMethodWithSuper_es6.ts, 35, 13))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
|
||||
// property access (assign)
|
||||
super.x = f;
|
||||
>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 23, 13))
|
||||
|
||||
// element access (assign)
|
||||
super["x"] = f;
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 23, 13))
|
||||
|
||||
// destructuring assign with property access
|
||||
({ f: super.x } = { f });
|
||||
>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 44, 10))
|
||||
>super.x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>x : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 44, 27))
|
||||
|
||||
// destructuring assign with element access
|
||||
({ f: super["x"] } = { f });
|
||||
>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 47, 10))
|
||||
>super : Symbol(A, Decl(asyncMethodWithSuper_es6.ts, 0, 0))
|
||||
>"x" : Symbol(A.x, Decl(asyncMethodWithSuper_es6.ts, 0, 9))
|
||||
>f : Symbol(f, Decl(asyncMethodWithSuper_es6.ts, 47, 30))
|
||||
}
|
||||
}
|
123
tests/baselines/reference/asyncMethodWithSuper_es6.types
Normal file
123
tests/baselines/reference/asyncMethodWithSuper_es6.types
Normal file
|
@ -0,0 +1,123 @@
|
|||
=== tests/cases/conformance/async/es6/asyncMethodWithSuper_es6.ts ===
|
||||
class A {
|
||||
>A : A
|
||||
|
||||
x() {
|
||||
>x : () => void
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
>B : B
|
||||
>A : A
|
||||
|
||||
// async method with only call/get on 'super' does not require a binding
|
||||
async simple() {
|
||||
>simple : () => Promise<void>
|
||||
|
||||
// call with property access
|
||||
super.x();
|
||||
>super.x() : void
|
||||
>super.x : () => void
|
||||
>super : A
|
||||
>x : () => void
|
||||
|
||||
// call with element access
|
||||
super["x"]();
|
||||
>super["x"]() : void
|
||||
>super["x"] : () => void
|
||||
>super : A
|
||||
>"x" : string
|
||||
|
||||
// property access (read)
|
||||
const a = super.x;
|
||||
>a : () => void
|
||||
>super.x : () => void
|
||||
>super : A
|
||||
>x : () => void
|
||||
|
||||
// element access (read)
|
||||
const b = super["x"];
|
||||
>b : () => void
|
||||
>super["x"] : () => void
|
||||
>super : A
|
||||
>"x" : string
|
||||
}
|
||||
|
||||
// async method with assignment/destructuring on 'super' requires a binding
|
||||
async advanced() {
|
||||
>advanced : () => Promise<void>
|
||||
|
||||
const f = () => {};
|
||||
>f : () => void
|
||||
>() => {} : () => void
|
||||
|
||||
// call with property access
|
||||
super.x();
|
||||
>super.x() : void
|
||||
>super.x : () => void
|
||||
>super : A
|
||||
>x : () => void
|
||||
|
||||
// call with element access
|
||||
super["x"]();
|
||||
>super["x"]() : void
|
||||
>super["x"] : () => void
|
||||
>super : A
|
||||
>"x" : string
|
||||
|
||||
// property access (read)
|
||||
const a = super.x;
|
||||
>a : () => void
|
||||
>super.x : () => void
|
||||
>super : A
|
||||
>x : () => void
|
||||
|
||||
// element access (read)
|
||||
const b = super["x"];
|
||||
>b : () => void
|
||||
>super["x"] : () => void
|
||||
>super : A
|
||||
>"x" : string
|
||||
|
||||
// property access (assign)
|
||||
super.x = f;
|
||||
>super.x = f : () => void
|
||||
>super.x : () => void
|
||||
>super : A
|
||||
>x : () => void
|
||||
>f : () => void
|
||||
|
||||
// element access (assign)
|
||||
super["x"] = f;
|
||||
>super["x"] = f : () => void
|
||||
>super["x"] : () => void
|
||||
>super : A
|
||||
>"x" : string
|
||||
>f : () => void
|
||||
|
||||
// destructuring assign with property access
|
||||
({ f: super.x } = { f });
|
||||
>({ f: super.x } = { f }) : { f: () => void; }
|
||||
>{ f: super.x } = { f } : { f: () => void; }
|
||||
>{ f: super.x } : { f: () => void; }
|
||||
>f : () => void
|
||||
>super.x : () => void
|
||||
>super : A
|
||||
>x : () => void
|
||||
>{ f } : { f: () => void; }
|
||||
>f : () => void
|
||||
|
||||
// destructuring assign with element access
|
||||
({ f: super["x"] } = { f });
|
||||
>({ f: super["x"] } = { f }) : { f: () => void; }
|
||||
>{ f: super["x"] } = { f } : { f: () => void; }
|
||||
>{ f: super["x"] } : { f: () => void; }
|
||||
>f : () => void
|
||||
>super["x"] : () => void
|
||||
>super : A
|
||||
>"x" : string
|
||||
>{ f } : { f: () => void; }
|
||||
>f : () => void
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.call(thisArg, _arguments)).next());
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
function f() {
|
||||
|
|
|
@ -36,7 +36,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator.throw(value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.call(thisArg, _arguments)).next());
|
||||
step((generator = generator.apply(thisArg, _arguments)).next());
|
||||
});
|
||||
};
|
||||
// async function without return type annotation - error
|
||||
|
|
|
@ -34,7 +34,7 @@ var Bar = (function (_super) {
|
|||
_super.apply(this, arguments);
|
||||
}
|
||||
Bar.prototype[symbol] = function () {
|
||||
return _super.prototype[symbol]();
|
||||
return _super.prototype[symbol].call(this);
|
||||
};
|
||||
return Bar;
|
||||
}(Foo));
|
||||
|
|
|
@ -34,7 +34,7 @@ var Bar = (function (_super) {
|
|||
_super.apply(this, arguments);
|
||||
}
|
||||
Bar[symbol] = function () {
|
||||
return _super[symbol]();
|
||||
return _super[symbol].call(this);
|
||||
};
|
||||
return Bar;
|
||||
}(Foo));
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
// @target: ES6
|
||||
// @noEmitHelpers: true
|
||||
class A {
|
||||
x() {
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
// async method with only call/get on 'super' does not require a binding
|
||||
async simple() {
|
||||
// call with property access
|
||||
super.x();
|
||||
|
||||
// call with element access
|
||||
super["x"]();
|
||||
|
||||
// property access (read)
|
||||
const a = super.x;
|
||||
|
||||
// element access (read)
|
||||
const b = super["x"];
|
||||
}
|
||||
|
||||
// async method with assignment/destructuring on 'super' requires a binding
|
||||
async advanced() {
|
||||
const f = () => {};
|
||||
|
||||
// call with property access
|
||||
super.x();
|
||||
|
||||
// call with element access
|
||||
super["x"]();
|
||||
|
||||
// property access (read)
|
||||
const a = super.x;
|
||||
|
||||
// element access (read)
|
||||
const b = super["x"];
|
||||
|
||||
// property access (assign)
|
||||
super.x = f;
|
||||
|
||||
// element access (assign)
|
||||
super["x"] = f;
|
||||
|
||||
// destructuring assign with property access
|
||||
({ f: super.x } = { f });
|
||||
|
||||
// destructuring assign with element access
|
||||
({ f: super["x"] } = { f });
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue