mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Cleanup and PR feedback
This commit is contained in:
+143
-67
@@ -7303,7 +7303,9 @@ module ts {
|
||||
if (globalPromiseType !== emptyObjectType) {
|
||||
// if the promised type is itself a promise, get the underlying type; otherwise, fallback to the promised type
|
||||
promisedType = getAwaitedType(promisedType);
|
||||
return createTypeReference(<GenericType>globalPromiseType, [promisedType]);
|
||||
if (promisedType !== unknownType) {
|
||||
return createTypeReference(<GenericType>globalPromiseType, [promisedType]);
|
||||
}
|
||||
}
|
||||
|
||||
error(location, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
||||
@@ -7319,17 +7321,23 @@ module ts {
|
||||
let isAsync = isAsyncFunctionLike(func);
|
||||
let type: Type;
|
||||
if (func.body.kind !== SyntaxKind.Block) {
|
||||
type = isAsync
|
||||
? checkAwaitedExpressionCached(<Expression>func.body, contextualMapper)
|
||||
: checkExpressionCached(<Expression>func.body, contextualMapper);
|
||||
if (isAsync) {
|
||||
type = checkAwaitedExpressionCached(<Expression>func.body, contextualMapper);
|
||||
}
|
||||
else {
|
||||
type = checkExpressionCached(<Expression>func.body, contextualMapper);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Aggregate the types of expressions within all the return statements.
|
||||
let types = checkAndAggregateReturnExpressionTypes(<Block>func.body, contextualMapper);
|
||||
if (types.length === 0) {
|
||||
return isAsync
|
||||
? createPromiseType(voidType, func)
|
||||
: voidType;
|
||||
if (isAsync) {
|
||||
return createPromiseType(voidType, func);
|
||||
}
|
||||
else {
|
||||
return voidType;
|
||||
}
|
||||
}
|
||||
|
||||
// When return statements are contextually typed we allow the return type to be a union type. Otherwise we require the
|
||||
@@ -7340,14 +7348,18 @@ module ts {
|
||||
return unknownType;
|
||||
}
|
||||
}
|
||||
|
||||
if (!contextualSignature) {
|
||||
reportErrorsFromWidening(func, type);
|
||||
}
|
||||
|
||||
let widenedType = getWidenedType(type);
|
||||
return isAsync
|
||||
? createPromiseType(widenedType, func)
|
||||
: widenedType;
|
||||
if (isAsync) {
|
||||
return createPromiseType(widenedType, func);
|
||||
}
|
||||
else {
|
||||
return widenedType;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a set of types relating to every return expression relating to a function block.
|
||||
@@ -7357,9 +7369,14 @@ module ts {
|
||||
forEachReturnStatement(body, returnStatement => {
|
||||
let expr = returnStatement.expression;
|
||||
if (expr) {
|
||||
let type = isAsync
|
||||
? checkAwaitedExpressionCached(expr, contextualMapper)
|
||||
: checkExpressionCached(expr, contextualMapper);
|
||||
let type: Type;
|
||||
if (isAsync) {
|
||||
type = checkAwaitedExpressionCached(expr, contextualMapper);
|
||||
}
|
||||
else {
|
||||
type = checkExpressionCached(expr, contextualMapper);
|
||||
}
|
||||
|
||||
if (!contains(aggregatedTypes, type)) {
|
||||
aggregatedTypes.push(type);
|
||||
}
|
||||
@@ -7495,10 +7512,12 @@ module ts {
|
||||
else {
|
||||
let exprType = checkExpression(<Expression>node.body);
|
||||
if (returnType) {
|
||||
checkTypeAssignableTo(
|
||||
isAsync ? getAwaitedType(exprType) : exprType,
|
||||
isAsync ? promisedType : returnType,
|
||||
node.body);
|
||||
if (isAsync) {
|
||||
checkTypeAssignableTo(getAwaitedType(exprType, node.body), promisedType, node.body);
|
||||
}
|
||||
else {
|
||||
checkTypeAssignableTo(exprType, returnType, node.body);
|
||||
}
|
||||
}
|
||||
checkFunctionExpressionBodies(node.body);
|
||||
}
|
||||
@@ -7619,8 +7638,8 @@ module ts {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.await_expression_must_be_contained_within_an_async_function);
|
||||
}
|
||||
|
||||
var operandType = checkExpression(node.expression);
|
||||
return getAwaitedType(operandType);
|
||||
let operandType = checkExpression(node.expression);
|
||||
return getAwaitedType(operandType, node);
|
||||
}
|
||||
|
||||
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
|
||||
@@ -8322,13 +8341,14 @@ module ts {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAsyncFunctionLike(node)) {
|
||||
var promiseConstructor = getPromiseConstructor(node);
|
||||
if (promiseConstructor) {
|
||||
var promiseIdentifier = getFirstIdentifier(promiseConstructor);
|
||||
var promiseName = promiseIdentifier.text;
|
||||
var typeSymbol = resolveName(node, promiseName, SymbolFlags.Type | SymbolFlags.Module, undefined, undefined);
|
||||
var valueSymbol = resolveName(node, promiseName, SymbolFlags.Value, undefined, undefined);
|
||||
var typeSymbol = resolveName(node, promiseName, SymbolFlags.Type | SymbolFlags.Module, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
||||
var valueSymbol = resolveName(node, promiseName, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined);
|
||||
if (typeSymbol !== valueSymbol) {
|
||||
var valueLinks = getNodeLinks(valueSymbol.valueDeclaration);
|
||||
if (!(valueLinks.flags & NodeCheckFlags.PromiseCollision)) {
|
||||
@@ -8932,8 +8952,28 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkNonThenableType(type: Type, location?: Node, message?: DiagnosticMessage) {
|
||||
if (!(type.flags & TypeFlags.Any) && isTypeAssignableTo(type, getGlobalThenableType())) {
|
||||
if (location) {
|
||||
if (!message) {
|
||||
message = Diagnostics.Operand_for_await_does_not_have_a_valid_callable_then_member;
|
||||
}
|
||||
|
||||
error(location, message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the "promised type" of a promise.
|
||||
* @param type The type of the promise.
|
||||
* @remarks The "promised type" of a type is the type of the "value" argument of the "onfulfilled" callback.
|
||||
*/
|
||||
function getPromisedType(type: Type): Type {
|
||||
// the "promised type" of a type is the type of the "value" argument of the "onfulfilled" callback.
|
||||
let globalPromiseLikeType = getInstantiatedGlobalPromiseLikeType();
|
||||
if (globalPromiseLikeType !== emptyObjectType && isTypeAssignableTo(type, globalPromiseLikeType)) {
|
||||
let thenProp = getPropertyOfType(type, "then");
|
||||
@@ -8954,67 +8994,100 @@ module ts {
|
||||
}
|
||||
|
||||
return getUnionType(awaitedTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return emptyObjectType;
|
||||
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
function getAwaitedType(type: Type): Type {
|
||||
// The "awaited type" of an expression is its "promised type" if the expression is a `Promise`; otherwise, it is the type of the expression.
|
||||
|
||||
|
||||
/**
|
||||
* Gets the "awaited type" of a type.
|
||||
* @param type The type to await.
|
||||
* @remarks The "awaited type" of an expression is its "promised type" if the expression is a
|
||||
* Promise-like type; otherwise, it is the type of the expression. This is used to reflect
|
||||
* The runtime behavior of the `await` keyword.
|
||||
*/
|
||||
function getAwaitedType(type: Type, location?: Node): Type {
|
||||
let promisedType = getPromisedType(type);
|
||||
if (promisedType === emptyObjectType) {
|
||||
return type;
|
||||
if (promisedType === unknownType) {
|
||||
// if we got the unknown type, the type wasn't a promise. We need to check to
|
||||
// ensure it is not a thenable.
|
||||
if (checkNonThenableType(type, location)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
return unknownType;
|
||||
}
|
||||
else if (promisedType === type) {
|
||||
// if we have a bad actor in the form of a promise whose promised type is the same
|
||||
// promise, return the unknown type as we cannot guess the shape.
|
||||
// if this were the actual case in the JavaScript, this Promise would never resolve.
|
||||
if (location) {
|
||||
error(location, Diagnostics.Operand_for_await_does_not_have_a_valid_callable_then_member);
|
||||
}
|
||||
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
// if we have a bad actor in the form of a promise whose promised type is the same promise, return the empty type.
|
||||
// if this were the actual case in the JavaScript, this Promise would never resolve.
|
||||
if (promisedType === type) {
|
||||
return emptyObjectType;
|
||||
}
|
||||
// `seen` keeps track of types we've tried to await to avoid cycles.
|
||||
// This is to protect against a bad actor with a mutually recursive promised type:
|
||||
//
|
||||
// declare class PromiseA {
|
||||
// then(onfulfilled: (value: PromiseB) => any, onrejected?);
|
||||
// }
|
||||
// declare class PromiseB {
|
||||
// then(onfulfilled: (value: PromiseA) => any, onrejected?);
|
||||
// }
|
||||
//
|
||||
let seen: boolean[];
|
||||
|
||||
// unwrap any nested promises
|
||||
let seen: boolean[];
|
||||
while (true) {
|
||||
let nestedPromisedType = getPromisedType(promisedType);
|
||||
if (nestedPromisedType === emptyObjectType) {
|
||||
// if this could not be unwrapped further, return the promised type
|
||||
return promisedType;
|
||||
if (nestedPromisedType === unknownType) {
|
||||
// this type could not be unwrapped further. We need to check to
|
||||
// ensure it is not a thenable
|
||||
if (checkNonThenableType(promisedType, location)) {
|
||||
return promisedType;
|
||||
}
|
||||
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
if (!seen) {
|
||||
// `seen` keeps track of types we've tried to await to avoid cycles
|
||||
seen = [];
|
||||
seen[type.id] = true;
|
||||
seen[promisedType.id] = true;
|
||||
}
|
||||
else if (seen[nestedPromisedType.id]) {
|
||||
// if we've already seen this type, this is a promise that would never resolve. As above, we return the empty type.
|
||||
return emptyObjectType;
|
||||
// if we've already seen this type, this is a promise that
|
||||
// would never resolve. As above, we return the unknown type.
|
||||
if (location) {
|
||||
error(location, Diagnostics.Operand_for_await_does_not_have_a_valid_callable_then_member);
|
||||
}
|
||||
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
seen[nestedPromisedType.id] = true;
|
||||
promisedType = nestedPromisedType;
|
||||
}
|
||||
|
||||
return promisedType;
|
||||
|
||||
// if we didn't get a promised type, check the type does not have a callable then member.
|
||||
if (isTypeAssignableTo(type, getGlobalThenableType())) {
|
||||
error(null, Diagnostics.Type_for_await_does_not_have_a_valid_callable_then_member);
|
||||
return emptyObjectType;
|
||||
}
|
||||
|
||||
// if the type was not a "promise" or a "thenable", return the type.
|
||||
return type;
|
||||
}
|
||||
|
||||
function checkAsyncFunctionReturnType(node: SignatureDeclaration, returnType: Type): Type {
|
||||
// This checks that an async function has a valid Promise-compatible return type, and returns the *awaited type* of the promise.
|
||||
// An async function has a valid Promise-compatible return type if the resolved value of the return type has a construct
|
||||
// signature that takes in an `initializer` function that in turn supplies a `resolve` function as one of its arguments
|
||||
// and results in an object with a callable `then` signature.
|
||||
/**
|
||||
* Checks the return type of an async function to ensure it is a compatible
|
||||
* Promise implementation.
|
||||
* @param node The signature to check
|
||||
* @param returnType The return type for the function
|
||||
* @remarks
|
||||
* This checks that an async function has a valid Promise-compatible return type,
|
||||
* and returns the *awaited type* of the promise. An async function has a valid
|
||||
* Promise-compatible return type if the resolved value of the return type has a
|
||||
* construct signature that takes in an `initializer` function that in turn supplies
|
||||
* a `resolve` function as one of its arguments and results in an object with a
|
||||
* callable `then` signature.
|
||||
*/
|
||||
function checkAsyncFunctionReturnType(node: SignatureDeclaration, returnType: Type): Type {
|
||||
let globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
|
||||
if (globalPromiseConstructorLikeType !== emptyObjectType) {
|
||||
if (!returnType) {
|
||||
@@ -9022,23 +9095,24 @@ module ts {
|
||||
}
|
||||
|
||||
// get the constructor type of the return type
|
||||
var declaredType = returnType.symbol ? getTypeOfSymbol(returnType.symbol) : emptyObjectType;
|
||||
let declaredType = returnType.symbol ? getTypeOfSymbol(returnType.symbol) : emptyObjectType;
|
||||
if (isTypeAssignableTo(declaredType, globalPromiseConstructorLikeType)) {
|
||||
var promisedType = getPromisedType(returnType);
|
||||
if (promisedType !== emptyObjectType) {
|
||||
let promisedType = getPromisedType(returnType);
|
||||
if (promisedType !== unknownType) {
|
||||
// unwrap the promised type
|
||||
var promiseConstructor = getPromiseConstructor(node);
|
||||
let promiseConstructor = getPromiseConstructor(node);
|
||||
if (promiseConstructor) {
|
||||
emitAwaiter = true;
|
||||
checkExpressionOrQualifiedName(promiseConstructor);
|
||||
return getAwaitedType(promisedType);
|
||||
}
|
||||
|
||||
emitAwaiter = true;
|
||||
return getAwaitedType(promisedType, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error(node, ts.Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
||||
return emptyObjectType;
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
/** Check a decorator */
|
||||
@@ -12351,9 +12425,11 @@ module ts {
|
||||
let thenPropertySymbol = createSymbol(SymbolFlags.Transient | SymbolFlags.Property, "then");
|
||||
getSymbolLinks(thenPropertySymbol).type = globalFunctionType;
|
||||
|
||||
let thenableType = <ResolvedType>createObjectType(TypeFlags.ObjectType);
|
||||
let thenableType = <ResolvedType>createObjectType(TypeFlags.Anonymous);
|
||||
thenableType.properties = [thenPropertySymbol];
|
||||
thenableType.members = createSymbolTable(thenableType.properties);
|
||||
thenableType.callSignatures = [];
|
||||
thenableType.constructSignatures = [];
|
||||
return thenableType;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ module ts {
|
||||
A_get_accessor_cannot_have_parameters: { code: 1054, category: DiagnosticCategory.Error, key: "A 'get' accessor cannot have parameters." },
|
||||
Accessors_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1056, category: DiagnosticCategory.Error, key: "Accessors are only available when targeting ECMAScript 5 and higher." },
|
||||
An_async_function_or_method_must_have_a_valid_awaitable_return_type: { code: 1057, category: DiagnosticCategory.Error, key: "An async function or method must have a valid awaitable return type." },
|
||||
Type_for_await_does_not_have_a_valid_callable_then_member: { code: 1058, category: DiagnosticCategory.Error, key: "Type for 'await' does not have a valid callable 'then' member." },
|
||||
Operand_for_await_does_not_have_a_valid_callable_then_member: { code: 1058, category: DiagnosticCategory.Error, key: "Operand for 'await' does not have a valid callable 'then' member." },
|
||||
Enum_member_must_have_initializer: { code: 1061, category: DiagnosticCategory.Error, key: "Enum member must have initializer." },
|
||||
An_export_assignment_cannot_be_used_in_a_namespace: { code: 1063, category: DiagnosticCategory.Error, key: "An export assignment cannot be used in a namespace." },
|
||||
Ambient_enum_elements_can_only_have_integer_literal_initializers: { code: 1066, category: DiagnosticCategory.Error, key: "Ambient enum elements can only have integer literal initializers." },
|
||||
@@ -381,11 +381,11 @@ module ts {
|
||||
An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2499, category: DiagnosticCategory.Error, key: "An interface can only extend an identifier/qualified-name with optional type arguments." },
|
||||
A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments: { code: 2500, category: DiagnosticCategory.Error, key: "A class can only implement an identifier/qualified-name with optional type arguments." },
|
||||
A_rest_element_cannot_contain_a_binding_pattern: { code: 2501, category: DiagnosticCategory.Error, key: "A rest element cannot contain a binding pattern." },
|
||||
_0_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 2502, category: DiagnosticCategory.Error, key: "'{0}' is referenced directly or indirectly in its own type annotation." },
|
||||
Cannot_find_namespace_0: { code: 2503, category: DiagnosticCategory.Error, key: "Cannot find namespace '{0}'." },
|
||||
Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions: { code: 2520, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions." },
|
||||
Expression_resolves_to_variable_declaration_0_that_compiler_uses_to_support_async_functions: { code: 2521, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '{0}' that compiler uses to support async functions." },
|
||||
The_arguments_object_cannot_be_referenced_in_an_async_arrow_function_Consider_using_a_standard_async_function_expression: { code: 2522, category: DiagnosticCategory.Error, key: "The 'arguments' object cannot be referenced in an async arrow function Consider using a standard async function expression." },
|
||||
_0_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 2502, category: DiagnosticCategory.Error, key: "'{0}' is referenced directly or indirectly in its own type annotation." },
|
||||
Cannot_find_namespace_0: { code: 2503, category: DiagnosticCategory.Error, key: "Cannot find namespace '{0}'." },
|
||||
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
"category": "Error",
|
||||
"code": 1057
|
||||
},
|
||||
"Type for 'await' does not have a valid callable 'then' member.": {
|
||||
"Operand for 'await' does not have a valid callable 'then' member.": {
|
||||
"category": "Error",
|
||||
"code": 1058
|
||||
},
|
||||
|
||||
+33
-17
@@ -568,11 +568,15 @@ module ts {
|
||||
}
|
||||
|
||||
function doOutsideOfContext<T>(context: ParserContextFlags, func: () => T): T {
|
||||
let setContextFlags = context & contextFlags;
|
||||
if (setContextFlags) {
|
||||
setContextFlag(false, setContextFlags);
|
||||
// contextFlagsToClear will contain only the context flags that are
|
||||
// currently set that we need to temporarily clear
|
||||
let contextFlagsToClear = context & contextFlags;
|
||||
if (contextFlagsToClear) {
|
||||
// clear the requested context flags
|
||||
setContextFlag(false, contextFlagsToClear);
|
||||
let result = func();
|
||||
setContextFlag(true, setContextFlags);
|
||||
// restore the context flags we just cleared
|
||||
setContextFlag(true, contextFlagsToClear);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -581,11 +585,15 @@ module ts {
|
||||
}
|
||||
|
||||
function doInsideOfContext<T>(context: ParserContextFlags, func: () => T): T {
|
||||
let unsetContextFlags = context & ~contextFlags;
|
||||
if (unsetContextFlags) {
|
||||
setContextFlag(true, unsetContextFlags);
|
||||
// contextFlagsToSet will contain only the context flags that
|
||||
// are not currently set that we need to temporarily enable
|
||||
let contextFlagsToSet = context & ~contextFlags;
|
||||
if (contextFlagsToSet) {
|
||||
// set the requested context flags
|
||||
setContextFlag(true, contextFlagsToSet);
|
||||
let result = func();
|
||||
setContextFlag(false, unsetContextFlags);
|
||||
// reset the context flags we just set
|
||||
setContextFlag(false, contextFlagsToSet);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1013,6 +1021,11 @@ module ts {
|
||||
}
|
||||
|
||||
function canFollowModifier(isArrowFunction?: boolean): boolean {
|
||||
// Arrow functions can have an `async` modifier, but the rules for what can follow that modifier
|
||||
// differ from the rules for any other declaration.
|
||||
// The `async` modifier on an async function can only be followed by an open parenthesis,
|
||||
// or a less than token (in the case of a generic arrow function).
|
||||
// In addition, the `async` modifier must appear on the same line as the following token.
|
||||
if (isArrowFunction) {
|
||||
if (scanner.hasPrecedingLineBreak()) {
|
||||
return false;
|
||||
@@ -1898,12 +1911,12 @@ module ts {
|
||||
|
||||
function parseBindingElementInitializer(inParameter: boolean) {
|
||||
// BindingElement[Yield,GeneratorParameter,Await,AsyncParameter] :
|
||||
// [+GeneratorParameter] BindingPattern[?Yield,?Await,GeneratorParameter] Initializer[In]opt
|
||||
// [+AsyncParameter] BindingPattern[?Yield,?Await,AsyncParameter] Initializer[In]opt
|
||||
// [+GeneratorParameter] BindingPattern[?Yield,?Await,?AsyncParameter,GeneratorParameter] Initializer[In]opt
|
||||
// [+AsyncParameter] BindingPattern[?Yield,?GeneratorParameter,?Await,AsyncParameter] Initializer[In]opt
|
||||
// [~GeneratorParameter,~AsyncParameter] BindingPattern[?Yield,?Await] Initializer[In,?Yield,?Await]opt
|
||||
// SingleNameBinding[Yield,GeneratorParameter,Await,AsyncParameter] :
|
||||
// [+GeneratorParameter] BindingIdentifier[Yield] Initializer[In]opt
|
||||
// [+AsyncParameter] BindingIdentifier[Await] Initializer[In]opt
|
||||
// [+GeneratorParameter] BindingIdentifier[Yield, ?Await] Initializer[In]opt
|
||||
// [+AsyncParameter] BindingIdentifier[Await, ?Yield] Initializer[In]opt
|
||||
// [~GeneratorParameter,~AsyncParameter] BindingIdentifier[?Yield,?Await] Initializer[In,?Yield,?Await]opt
|
||||
let parseInitializer = inParameter ? parseParameterInitializer : parseNonParameterInitializer;
|
||||
return inGeneratorParameterOrAsyncParameterContext()
|
||||
@@ -2425,9 +2438,9 @@ module ts {
|
||||
case SyntaxKind.LessThanToken:
|
||||
case SyntaxKind.AwaitKeyword:
|
||||
case SyntaxKind.YieldKeyword:
|
||||
// Yield always starts an expression. Either it is an identifier (in which case
|
||||
// Yield/await always starts an expression. Either it is an identifier (in which case
|
||||
// it is definitely an expression). Or it's a keyword (either because we're in
|
||||
// a generator, or in strict mode (or both)) and it started a yield expression.
|
||||
// a generator or async function, or in strict mode (or both)) and it started a yield or await expression.
|
||||
return true;
|
||||
default:
|
||||
// Error tolerance. If we see the start of some binary operator, we consider
|
||||
@@ -3317,6 +3330,9 @@ module ts {
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
return parseObjectLiteralExpression();
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
// Async arrow functions are parsed earlier in parseAssignmentExpressionOrHigher.
|
||||
// If we encounter `async [no LineTerminator here] function` then this is an async
|
||||
// function; otherwise, its an identifier.
|
||||
if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
|
||||
break;
|
||||
}
|
||||
@@ -3450,7 +3466,7 @@ module ts {
|
||||
parseExpected(SyntaxKind.FunctionKeyword);
|
||||
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
|
||||
|
||||
let isGenerator = node.asteriskToken != undefined;
|
||||
let isGenerator = !!node.asteriskToken;
|
||||
let isAsync = isAsyncFunctionLike(node);
|
||||
node.name =
|
||||
isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalIdentifier) :
|
||||
@@ -4092,7 +4108,7 @@ module ts {
|
||||
parseExpected(SyntaxKind.FunctionKeyword);
|
||||
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
|
||||
node.name = node.flags & NodeFlags.Default ? parseOptionalIdentifier() : parseIdentifier();
|
||||
let isGenerator = node.asteriskToken != undefined;
|
||||
let isGenerator = !!node.asteriskToken;
|
||||
let isAsync = isAsyncFunctionLike(node);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ isGenerator, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList:*/ false, node);
|
||||
node.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, Diagnostics.or_expected);
|
||||
@@ -4116,7 +4132,7 @@ module ts {
|
||||
method.asteriskToken = asteriskToken;
|
||||
method.name = name;
|
||||
method.questionToken = questionToken;
|
||||
let isGenerator = asteriskToken != undefined;
|
||||
let isGenerator = !!asteriskToken;
|
||||
let isAsync = isAsyncFunctionLike(method);
|
||||
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ isGenerator, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList:*/ false, method);
|
||||
method.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, diagnosticMessage);
|
||||
|
||||
@@ -344,16 +344,16 @@ module ts {
|
||||
// If this node was parsed as part of a decorator
|
||||
Decorator = 1 << 4,
|
||||
|
||||
// If this node was parsed in the parameters of an async function.
|
||||
AsyncParameter = 1 << 5,
|
||||
|
||||
// If this node was parsed in the 'await' context created when parsing an async function.
|
||||
Await = 1 << 6,
|
||||
|
||||
// If the parser encountered an error when parsing the code that created this node. Note
|
||||
// the parser only sets this directly on the node it creates right after encountering the
|
||||
// error.
|
||||
ThisNodeHasError = 1 << 5,
|
||||
|
||||
// If this node was parsed in the parameters of an async function.
|
||||
AsyncParameter = 1 << 6,
|
||||
|
||||
// If this node was parsed in the 'await' context created when parsing an async function.
|
||||
Await = 1 << 7,
|
||||
ThisNodeHasError = 1 << 7,
|
||||
|
||||
// Context flags set directly by the parser.
|
||||
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError | AsyncParameter | Await,
|
||||
|
||||
Reference in New Issue
Block a user