diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fae3e08edcc..3801c317d61 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9884,15 +9884,15 @@ namespace ts { const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn; if (returnType && !hasExplicitReturn) { - // minimal check: function has syntactic return type annotation and no explicit return statements in the body + // minimal check: function has syntactic return type annotation and no explicit return statements in the body // this function does not conform to the specification. - // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present + // NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } else if (compilerOptions.noImplicitReturns) { if (!returnType) { // If return type annotation is omitted check if function has any explicit return statements. - // If it does not have any - its inferred return type is void - don't do any checks. + // If it does not have any - its inferred return type is void - don't do any checks. // Otherwise get inferred return type from function body and report error only if it is not void / anytype const inferredReturnType = hasExplicitReturn ? getReturnTypeOfSignature(getSignatureFromDeclaration(func)) @@ -11922,13 +11922,8 @@ namespace ts { return unknownType; } - // If the constructor, resolved locally, is an alias symbol we should mark it as referenced. - const promiseName = getEntityNameFromTypeNode(node.type); - const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName); - const promiseAliasSymbol = resolveName(node, promiseNameOrNamespaceRoot.text, SymbolFlags.Alias, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined); - if (promiseAliasSymbol) { - markAliasSymbolAsReferenced(promiseAliasSymbol); - } + // If the Promise constructor, resolved locally, is an alias symbol we should mark it as referenced. + checkReturnTypeAnnotationAsExpression(node); // Validate the promise constructor type. const promiseConstructorType = getTypeOfSymbol(promiseConstructor); @@ -11937,6 +11932,8 @@ namespace ts { } // Verify there is no local declaration that could collide with the promise constructor. + const promiseName = getEntityNameFromTypeNode(node.type); + const promiseNameOrNamespaceRoot = getFirstIdentifier(promiseName); const rootSymbol = getSymbol(node.locals, promiseNameOrNamespaceRoot.text, SymbolFlags.Value); if (rootSymbol) { error(rootSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, @@ -12024,24 +12021,12 @@ namespace ts { * Checks the type annotation of an accessor declaration or property declaration as * an expression if it is a type reference to a type with a value declaration. */ - function checkTypeAnnotationAsExpression(node: AccessorDeclaration | PropertyDeclaration | ParameterDeclaration | MethodDeclaration) { - switch (node.kind) { - case SyntaxKind.PropertyDeclaration: - checkTypeNodeAsExpression((node).type); - break; - case SyntaxKind.Parameter: - checkTypeNodeAsExpression((node).type); - break; - case SyntaxKind.MethodDeclaration: - checkTypeNodeAsExpression((node).type); - break; - case SyntaxKind.GetAccessor: - checkTypeNodeAsExpression((node).type); - break; - case SyntaxKind.SetAccessor: - checkTypeNodeAsExpression(getSetAccessorTypeAnnotationNode(node)); - break; - } + function checkTypeAnnotationAsExpression(node: VariableLikeDeclaration) { + checkTypeNodeAsExpression((node).type); + } + + function checkReturnTypeAnnotationAsExpression(node: FunctionLikeDeclaration) { + checkTypeNodeAsExpression(node.type); } /** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */ @@ -12079,11 +12064,12 @@ namespace ts { break; case SyntaxKind.MethodDeclaration: - checkParameterTypeAnnotationsAsExpressions(node); - // fall-through - - case SyntaxKind.SetAccessor: case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + checkParameterTypeAnnotationsAsExpressions(node); + checkReturnTypeAnnotationAsExpression(node); + break; + case SyntaxKind.PropertyDeclaration: case SyntaxKind.Parameter: checkTypeAnnotationAsExpression(node); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 48f9dd32aaf..3e6c2e321c2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2190,7 +2190,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emit(node.right); } - function emitEntityNameAsExpression(node: EntityName, useFallback: boolean) { + function emitEntityNameAsExpression(node: EntityName | Expression, useFallback: boolean) { switch (node.kind) { case SyntaxKind.Identifier: if (useFallback) { @@ -2205,6 +2205,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi case SyntaxKind.QualifiedName: emitQualifiedNameAsExpression(node, useFallback); break; + + default: + emitNodeWithoutSourceMap(node); + break; } } @@ -2980,7 +2984,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } else { // this is top level converted loop so we need to create an alias for 'this' here - // NOTE: + // NOTE: // if converted loops were all nested in arrow function then we'll always emit '_this' so convertedLoopState.thisName will not be set. // If it is set this means that all nested loops are not nested in arrow function and it is safe to capture 'this'. write(`var ${convertedLoopState.thisName} = this;`); @@ -4457,18 +4461,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write(" __awaiter(this"); if (hasLexicalArguments) { - write(", arguments"); + write(", arguments, "); } else { - write(", void 0"); + write(", void 0, "); } if (promiseConstructor) { - write(", "); - emitNodeWithoutSourceMap(promiseConstructor); + emitEntityNameAsExpression(promiseConstructor, /*useFallback*/ false); } else { - write(", Promise"); + write("Promise"); } // Emit the call to __awaiter. @@ -5744,7 +5747,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } /** Serializes the return type of function. Used by the __metadata decorator for a method. */ - function emitSerializedReturnTypeOfNode(node: Node): string | string[] { + function emitSerializedReturnTypeOfNode(node: Node) { if (node && isFunctionLike(node) && (node).type) { emitSerializedTypeNode((node).type); return; diff --git a/tests/baselines/reference/asyncImportedPromise_es6.js b/tests/baselines/reference/asyncImportedPromise_es6.js index 81c36200821..a9c7540d88f 100644 --- a/tests/baselines/reference/asyncImportedPromise_es6.js +++ b/tests/baselines/reference/asyncImportedPromise_es6.js @@ -32,6 +32,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi var task_1 = require("./task"); class Test { example() { - return __awaiter(this, void 0, Task, function* () { return; }); + return __awaiter(this, void 0, task_1.Task, function* () { return; }); } }