Added types, scan, parse, and check for async functions

This commit is contained in:
Ron Buckton 2015-05-05 17:57:21 -07:00
parent 15f4b58d6c
commit d19a200750
9 changed files with 906 additions and 193 deletions

View file

@ -89,7 +89,7 @@ module ts {
let nullType = createIntrinsicType(TypeFlags.Null | TypeFlags.ContainsUndefinedOrNull, "null");
let unknownType = createIntrinsicType(TypeFlags.Any, "unknown");
let resolvingType = createIntrinsicType(TypeFlags.Any, "__resolving__");
let emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
let anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
let noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
@ -101,6 +101,8 @@ module ts {
let globalArraySymbol: Symbol;
let globalESSymbolConstructorSymbol: Symbol;
let getGlobalPromiseSymbol: () => Symbol;
let globalObjectType: ObjectType;
let globalFunctionType: ObjectType;
@ -118,6 +120,11 @@ module ts {
let getGlobalParameterDecoratorType: () => ObjectType;
let getGlobalPropertyDecoratorType: () => ObjectType;
let getGlobalMethodDecoratorType: () => ObjectType;
let getGlobalPromiseType: () => ObjectType;
let getGlobalPromiseLikeType: () => ObjectType;
let getInstantiatedGlobalPromiseLikeType: () => ObjectType;
let getGlobalPromiseConstructorLikeType: () => ObjectType;
let getGlobalThenableType: () => ObjectType;
let tupleTypes: Map<TupleType> = {};
let unionTypes: Map<UnionType> = {};
@ -125,11 +132,14 @@ module ts {
let emitExtends = false;
let emitDecorate = false;
let emitParam = false;
let emitAwaiter = false;
let emitGenerator = false;
let mergedSymbols: Symbol[] = [];
let symbolLinks: SymbolLinks[] = [];
let nodeLinks: NodeLinks[] = [];
let potentialThisCollisions: Node[] = [];
var potentialArgumentsCollisions: Node[] = [];
let diagnostics = createDiagnosticCollection();
@ -5146,9 +5156,11 @@ module ts {
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.AwaitExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.YieldExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.SpreadElementExpression:
case SyntaxKind.Block:
@ -5406,8 +5418,14 @@ module ts {
// will be bound to non-arrow function that contain this arrow function. This results in inconsistent behavior.
// To avoid that we will give an error to users if they use arguments objects in arrow function so that they
// can explicitly bound arguments objects
if (symbol === argumentsSymbol && getContainingFunction(node).kind === SyntaxKind.ArrowFunction && languageVersion < ScriptTarget.ES6) {
error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
let container = getContainingFunction(node);
if (symbol === argumentsSymbol) {
if (container.kind === SyntaxKind.ArrowFunction && languageVersion < ScriptTarget.ES6) {
error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
}
else if (node.parserContextFlags & ParserContextFlags.Await) {
captureLexicalArguments(node, container);
}
}
if (symbol.flags & SymbolFlags.Alias && !isInTypeQuery(node) && !isConstEnumOrConstEnumOnlyModule(resolveAlias(symbol))) {
@ -5416,6 +5434,7 @@ module ts {
checkCollisionWithCapturedSuperVariable(node, node);
checkCollisionWithCapturedThisVariable(node, node);
checkCollisionWithCapturedArgumentsVariable(node, node);
checkBlockScopedBindingCapturedInLoop(node, symbol);
return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node);
@ -5497,6 +5516,11 @@ module ts {
// When targeting es6, arrow function lexically bind "this" so we do not need to do the work of binding "this" in emitted code
needToCaptureLexicalThis = (languageVersion < ScriptTarget.ES6);
}
if (node.parserContextFlags & ParserContextFlags.Await) {
// if 'this' is part of an async function, we will need to capture 'this'
needToCaptureLexicalThis = true;
}
switch (container.kind) {
case SyntaxKind.ModuleDeclaration:
@ -5537,6 +5561,14 @@ module ts {
return anyType;
}
function captureLexicalArguments(node: Node, container: Node): void {
if (node.parent.kind !== SyntaxKind.Parameter) {
getNodeLinks(node).flags |= NodeCheckFlags.LexicalArguments;
}
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
}
function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean {
for (let n = node; n && n !== constructorDecl; n = n.parent) {
if (n.kind === SyntaxKind.Parameter) {
@ -7220,22 +7252,42 @@ module ts {
links.type = instantiateType(getTypeOfSymbol(lastOrUndefined(context.parameters)), mapper);
}
}
function createPromiseType(promisedType: Type, location: Node): Type {
// creates a `Promise<T>` type where `T` is the promisedType argument
let globalPromiseType = getGlobalPromiseType();
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]);
}
error(location, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
return unknownType;
}
function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type {
let contextualSignature = getContextualSignatureForFunctionLikeDeclaration(func);
if (!func.body) {
return unknownType;
}
let isAsync = isAsyncFunctionLike(func);
let type: Type;
if (func.body.kind !== SyntaxKind.Block) {
type = checkExpressionCached(<Expression>func.body, contextualMapper);
type = isAsync
? checkAwaitedExpressionCached(<Expression>func.body, contextualMapper)
: 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 voidType;
return isAsync
? createPromiseType(voidType, func)
: voidType;
}
// When return statements are contextually typed we allow the return type to be a union type. Otherwise we require the
// return expressions to have a best common supertype.
type = contextualSignature ? getUnionType(types) : getCommonSupertype(types);
@ -7247,17 +7299,23 @@ module ts {
if (!contextualSignature) {
reportErrorsFromWidening(func, type);
}
return getWidenedType(type);
let widenedType = getWidenedType(type);
return isAsync
? createPromiseType(widenedType, func)
: type;
}
/// Returns a set of types relating to every return expression relating to a function block.
function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper): Type[] {
function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper, isAsync?: boolean): Type[] {
let aggregatedTypes: Type[] = [];
forEachReturnStatement(body, returnStatement => {
let expr = returnStatement.expression;
if (expr) {
let type = checkExpressionCached(expr, contextualMapper);
let type = isAsync
? checkAwaitedExpressionCached(expr, contextualMapper)
: checkExpressionCached(expr, contextualMapper);
if (!contains(aggregatedTypes, type)) {
aggregatedTypes.push(type);
}
@ -7327,6 +7385,12 @@ module ts {
if (contextualMapper === identityMapper && isContextSensitive(node)) {
return anyFunctionType;
}
let isAsync = isAsyncFunctionLike(node);
if (isAsync) {
emitAwaiter = true;
}
let links = getNodeLinks(node);
let type = getTypeOfSymbol(node.symbol);
// Check if function expression is contextually typed and assign parameter types if so
@ -7357,6 +7421,7 @@ module ts {
if (produceDiagnostics && node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) {
checkCollisionWithCapturedSuperVariable(node, (<FunctionExpression>node).name);
checkCollisionWithCapturedThisVariable(node, (<FunctionExpression>node).name);
checkCollisionWithCapturedArgumentsVariable(node, (<FunctionExpression>node).name);
}
return type;
@ -7364,8 +7429,21 @@ module ts {
function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
if (node.type && !node.asteriskToken) {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
let isAsync = isAsyncFunctionLike(node);
let returnType = node.type && getTypeFromTypeNode(node.type);
let promisedType: Type;
if (returnType && isAsync) {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so we
// should not be checking assignability of a promise to the return type. Instead, we need to
// check assignability of the awaited type of the concise body against the promised type of
// its return type annotation.
promisedType = checkAsyncFunctionReturnType(node, returnType);
}
if (returnType && !node.asteriskToken) {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
}
if (node.body) {
@ -7374,8 +7452,11 @@ module ts {
}
else {
let exprType = checkExpression(<Expression>node.body);
if (node.type) {
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
if (returnType) {
checkTypeAssignableTo(
isAsync ? getAwaitedType(exprType) : exprType,
isAsync ? promisedType : returnType,
node.body);
}
checkFunctionExpressionBodies(node.body);
}
@ -7490,6 +7571,22 @@ module ts {
return undefinedType;
}
function checkAwaitExpression(node: AwaitExpression): Type {
// Grammar checking
if (!(node.parserContextFlags & ParserContextFlags.Await)) {
var parameter = getContainingParameter(node);
if (parameter && parameter.parserContextFlags & ParserContextFlags.Await) {
grammarErrorAfterFirstToken(node, Diagnostics._0_expression_is_not_allowed_in_an_initializer, "await");
}
else {
grammarErrorOnFirstToken(node, Diagnostics.await_expression_must_be_contained_within_an_async_function);
}
}
var operandType = checkExpression(node.expression);
return getAwaitedType(operandType);
}
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
// Grammar checking
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
@ -7897,7 +7994,13 @@ module ts {
function checkYieldExpression(node: YieldExpression): void {
// Grammar checking
if (!(node.parserContextFlags & ParserContextFlags.Yield)) {
grammarErrorOnFirstToken(node, Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
let parameter = getContainingParameter(node);
if (parameter && (parameter.parserContextFlags & ParserContextFlags.GeneratorParameter)) {
grammarErrorAfterFirstToken(node, Diagnostics._0_expression_is_not_allowed_in_an_initializer, "yield");
}
else {
grammarErrorOnFirstToken(node, Diagnostics.yield_expression_must_be_contained_within_a_generator_declaration);
}
}
else {
grammarErrorOnFirstToken(node, Diagnostics.yield_expressions_are_not_currently_supported);
@ -7931,6 +8034,15 @@ module ts {
node.contextualType = saveContextualType;
return result;
}
function checkAwaitedExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
let links = getNodeLinks(node);
if (!links.resolvedAwaitedType) {
links.resolvedAwaitedType = getAwaitedType(checkExpressionCached(node, contextualMapper));
}
return links.resolvedAwaitedType;
}
function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
let links = getNodeLinks(node);
@ -8078,6 +8190,8 @@ module ts {
return checkDeleteExpression(<DeleteExpression>node);
case SyntaxKind.VoidExpression:
return checkVoidExpression(<VoidExpression>node);
case SyntaxKind.AwaitExpression:
return checkAwaitExpression(<AwaitExpression>node);
case SyntaxKind.PrefixUnaryExpression:
return checkPrefixUnaryExpression(<PrefixUnaryExpression>node);
case SyntaxKind.PostfixUnaryExpression:
@ -8166,6 +8280,7 @@ module ts {
}
if (produceDiagnostics) {
checkCollisionWithAwaiterVariablesInGeneratedCode(node, node.name);
checkCollisionWithArgumentsInGeneratedCode(node);
if (compilerOptions.noImplicitAny && !node.type) {
switch (node.kind) {
@ -8177,6 +8292,22 @@ 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);
if (typeSymbol !== valueSymbol) {
var valueLinks = getNodeLinks(valueSymbol.valueDeclaration);
if (!(valueLinks.flags & NodeCheckFlags.PromiseCollision)) {
valueLinks.flags |= NodeCheckFlags.PromiseCollision;
error(valueSymbol.valueDeclaration, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, promiseName, getTextOfNode(promiseConstructor));
}
}
}
}
}
checkSpecializedSignatureDeclaration(node);
@ -8772,6 +8903,113 @@ module ts {
}
}
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 awaitedTypes: Type[] = [];
let thenProp = getPropertyOfType(type, "then");
let thenType = getTypeOfSymbol(thenProp);
let thenSignatures = getSignaturesOfType(thenType, SignatureKind.Call);
for (let thenSignature of thenSignatures) {
thenSignature = getErasedSignature(thenSignature);
let onfulfilledParameterType = getTypeAtPosition(thenSignature, 0);
let onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, SignatureKind.Call);
for (let onfulfilledParameterSignature of onfulfilledParameterSignatures) {
let valueParameterType = getTypeAtPosition(onfulfilledParameterSignature, 0);
if (valueParameterType !== type) {
awaitedTypes.push(valueParameterType);
}
}
}
return getUnionType(awaitedTypes);
}
return emptyObjectType;
}
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.
let promisedType = getPromisedType(type);
if (promisedType === emptyObjectType) {
return type;
}
// 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;
}
// 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 (!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;
}
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.
let globalPromiseConstructorLikeType = getGlobalPromiseConstructorLikeType();
if (globalPromiseConstructorLikeType !== emptyObjectType) {
if (!returnType) {
returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(node));
}
// get the constructor type of the return type
var declaredType = returnType.symbol ? getTypeOfSymbol(returnType.symbol) : emptyObjectType;
if (isTypeAssignableTo(declaredType, globalPromiseConstructorLikeType)) {
var promisedType = getPromisedType(returnType);
if (promisedType !== emptyObjectType) {
// unwrap the promised type
var promiseConstructor = getPromiseConstructor(node);
if (promiseConstructor) {
emitAwaiter = true;
checkExpressionOrQualifiedName(promiseConstructor);
return getAwaitedType(promisedType);
}
}
}
}
error(node, ts.Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
return emptyObjectType;
}
/** Check a decorator */
function checkDecorator(node: Decorator): void {
let expression: Expression = node.expression;
@ -8904,6 +9142,7 @@ module ts {
checkCollisionWithCapturedSuperVariable(node, node.name);
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithCapturedArgumentsVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
}
}
@ -8946,7 +9185,14 @@ module ts {
checkSourceElement(node.body);
if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
let returnType = getTypeFromTypeNode(node.type);
let isAsync = isAsyncFunctionLike(node);
let promisedType: Type;
if (isAsync) {
promisedType = checkAsyncFunctionReturnType(node, returnType);
}
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
}
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
@ -9016,6 +9262,12 @@ module ts {
}
}
function checkCollisionWithCapturedArgumentsVariable(node: Node, name: Identifier): void {
if (needCollisionCheckForIdentifier(node, name, "_arguments")) {
potentialArgumentsCollisions.push(node);
}
}
// this function will run after checking the source file so 'CaptureThis' is correct for all nodes
function checkIfThisIsCapturedInEnclosingScope(node: Node): void {
let current = node;
@ -9034,6 +9286,25 @@ module ts {
}
}
function checkIfArgumentsIsCapturedInEnclosingScope(node: Node): void {
let current = node;
while (current) {
if (getNodeCheckFlags(current) & NodeCheckFlags.CaptureArguments) {
let isDeclaration = node.kind !== SyntaxKind.Identifier;
if (isDeclaration) {
error((<Declaration>node).name, Diagnostics.Duplicate_identifier_arguments_Compiler_uses_variable_declaration_arguments_to_capture_arguments_reference);
}
else {
error(node, Diagnostics.Expression_resolves_to_variable_declaration_arguments_that_compiler_uses_to_capture_arguments_reference);
}
return;
}
current = current.parent;
}
}
function checkCollisionWithCapturedSuperVariable(node: Node, name: Identifier) {
if (!needCollisionCheckForIdentifier(node, name, "_super")) {
return;
@ -9149,6 +9420,34 @@ module ts {
}
}
function getPromiseConstructor(node: SignatureDeclaration): EntityName {
if (node.type && node.type.kind === SyntaxKind.TypeReference) {
return (<TypeReferenceNode>node.type).typeName;
}
let globalPromiseSymbol = getGlobalPromiseSymbol();
if (globalPromiseSymbol && globalPromiseSymbol === resolveName(node, "Promise", SymbolFlags.Value, undefined, undefined)) {
return <Identifier>globalPromiseSymbol.valueDeclaration.name;
}
return undefined;
}
function checkCollisionWithAwaiterVariablesInGeneratedCode(node: Node, name: DeclarationName): void {
if (!name || name.kind !== SyntaxKind.Identifier || isTypeNode(name)) {
return;
}
let identifier = <Identifier>name;
let container = getContainingFunction(name);
if (container && isAsyncFunctionLike(container) && node.kind !== SyntaxKind.Identifier) {
var promiseConstructor = getPromiseConstructor(container);
if (promiseConstructor && promiseConstructor.kind === SyntaxKind.Identifier && (<Identifier>promiseConstructor).text === identifier.text) {
error(node, Diagnostics.Duplicate_identifier_0_Compiler_uses_declaration_1_to_support_async_functions, identifier.text, getTextOfNode(promiseConstructor));
}
}
}
function isParameterDeclaration(node: VariableLikeDeclaration) {
while (node.kind === SyntaxKind.BindingElement) {
node = <VariableLikeDeclaration>node.parent.parent;
@ -9251,8 +9550,14 @@ module ts {
}
checkCollisionWithCapturedSuperVariable(node, <Identifier>node.name);
checkCollisionWithCapturedThisVariable(node, <Identifier>node.name);
checkCollisionWithCapturedArgumentsVariable(node, <Identifier>node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, <Identifier>node.name);
}
if (symbol === argumentsSymbol && (node.parserContextFlags & ParserContextFlags.Await)) {
let container = getContainingFunction(node);
captureLexicalArguments(node.name, container);
}
}
function checkVariableDeclaration(node: VariableDeclaration) {
@ -9275,7 +9580,10 @@ module ts {
function checkGrammarDisallowedModifiersInBlockOrObjectLiteralExpression(node: Node) {
if (node.modifiers) {
if (inBlockOrObjectLiteralExpression(node)) {
return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
// disallow all but the `async` modifier here
if (isAccessor(node.kind) || !isFunctionLike(node) || (node.modifiers.flags & ~NodeFlags.Async)) {
return grammarErrorOnFirstToken(node, Diagnostics.Modifiers_cannot_appear_here);
}
}
}
}
@ -9288,6 +9596,8 @@ module ts {
node = node.parent;
}
return false;
}
function checkExpressionStatement(node: ExpressionStatement) {
@ -9667,8 +9977,11 @@ module ts {
error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
}
}
else if (func.type && !isAccessor(func.kind) && isAsyncFunctionLike(func)) {
checkTypeAssignableTo(getAwaitedType(exprType), getPromisedType(returnType), node.expression);
}
else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func)) {
checkTypeAssignableTo(exprType, returnType, node.expression, /*headMessage*/ undefined);
checkTypeAssignableTo(exprType, returnType, node.expression);
}
}
}
@ -9943,6 +10256,7 @@ module ts {
checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0);
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
checkCollisionWithAwaiterVariablesInGeneratedCode(node, node.name);
}
checkTypeParameters(node.typeParameters);
checkExportsOnMergedDeclarations(node);
@ -10386,6 +10700,7 @@ module ts {
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
checkCollisionWithCapturedThisVariable(node, node.name);
checkCollisionWithRequireExportsInGeneratedCode(node, node.name);
checkCollisionWithAwaiterVariablesInGeneratedCode(node, node.name);
checkExportsOnMergedDeclarations(node);
computeEnumMemberValues(node);
@ -10885,12 +11200,14 @@ module ts {
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.AwaitExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.BinaryExpression:
case SyntaxKind.ConditionalExpression:
case SyntaxKind.SpreadElementExpression:
case SyntaxKind.YieldExpression:
case SyntaxKind.Block:
case SyntaxKind.ModuleBlock:
case SyntaxKind.VariableStatement:
@ -10941,6 +11258,7 @@ module ts {
emitDecorate = false;
emitParam = false;
potentialThisCollisions.length = 0;
potentialArgumentsCollisions.length = 0;
forEach(node.statements, checkSourceElement);
checkFunctionExpressionBodies(node);
@ -10953,6 +11271,11 @@ module ts {
forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
potentialThisCollisions.length = 0;
}
if (potentialArgumentsCollisions.length) {
forEach(potentialArgumentsCollisions, checkIfArgumentsIsCapturedInEnclosingScope);
potentialArgumentsCollisions.length = 0;
}
if (emitExtends) {
links.flags |= NodeCheckFlags.EmitExtends;
@ -10965,6 +11288,14 @@ module ts {
if (emitParam) {
links.flags |= NodeCheckFlags.EmitParam;
}
if (emitAwaiter) {
links.flags |= NodeCheckFlags.EmitAwaiter;
}
if (emitGenerator || (emitAwaiter && languageVersion < ScriptTarget.ES6)) {
links.flags |= NodeCheckFlags.EmitGenerator;
}
links.flags |= NodeCheckFlags.TypeChecked;
}
@ -11982,6 +12313,12 @@ module ts {
getGlobalPropertyDecoratorType = memoize(() => getGlobalType("PropertyDecorator"));
getGlobalMethodDecoratorType = memoize(() => getGlobalType("MethodDecorator"));
getGlobalParameterDecoratorType = memoize(() => getGlobalType("ParameterDecorator"));
getGlobalPromiseSymbol = memoize(() => getGlobalTypeSymbol("Promise"));
getGlobalPromiseType = memoize(() => getTypeOfGlobalSymbol(getGlobalPromiseSymbol(), /*arity*/ 1));
getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1));
getInstantiatedGlobalPromiseLikeType = memoize(createInstantiatedPromiseLikeType);
getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike"));
getGlobalThenableType = memoize(createThenableType);
// If we're in ES6 mode, load the TemplateStringsArray.
// Otherwise, default to 'unknown' for the purposes of type checking in LS scenarios.
@ -12003,6 +12340,26 @@ module ts {
anyArrayType = createArrayType(anyType);
}
function createInstantiatedPromiseLikeType(): ObjectType {
let promiseLikeType = getGlobalPromiseLikeType();
if (promiseLikeType !== emptyObjectType) {
return createTypeReference(<GenericType>promiseLikeType, [anyType]);
}
return emptyObjectType;
}
function createThenableType() {
// build the thenable type that is used to verify against a non-promise "thenable" operand to `await`.
let thenPropertySymbol = createSymbol(SymbolFlags.Transient | SymbolFlags.Property, "then");
getSymbolLinks(thenPropertySymbol).type = globalFunctionType;
let thenableType = <ResolvedType>createObjectType(TypeFlags.ObjectType);
thenableType.properties = [thenPropertySymbol];
thenableType.members = createSymbolTable(thenableType.properties);
return thenableType;
}
// GRAMMAR CHECKING
function isReservedWordInStrictMode(node: Identifier): boolean {
@ -12203,7 +12560,7 @@ module ts {
return;
}
let lastStatic: Node, lastPrivate: Node, lastProtected: Node, lastDeclare: Node;
let lastStatic: Node, lastPrivate: Node, lastProtected: Node, lastDeclare: Node, lastAsync: Node;
let flags = 0;
for (let modifier of node.modifiers) {
switch (modifier.kind) {
@ -12229,6 +12586,9 @@ module ts {
else if (flags & NodeFlags.Static) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "static");
}
else if (flags & NodeFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, text, "async");
}
else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_element, text);
}
@ -12239,6 +12599,9 @@ module ts {
if (flags & NodeFlags.Static) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "static");
}
else if (flags & NodeFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "static", "async");
}
else if (node.parent.kind === SyntaxKind.ModuleBlock || node.parent.kind === SyntaxKind.SourceFile) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_module_element, "static");
}
@ -12256,6 +12619,9 @@ module ts {
else if (flags & NodeFlags.Ambient) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "declare");
}
else if (flags & NodeFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_must_precede_1_modifier, "export", "async");
}
else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_class_element, "export");
}
@ -12269,6 +12635,9 @@ module ts {
if (flags & NodeFlags.Ambient) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "declare");
}
else if (flags & NodeFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async");
}
else if (node.parent.kind === SyntaxKind.ClassDeclaration) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_class_element, "declare");
}
@ -12281,6 +12650,20 @@ module ts {
flags |= NodeFlags.Ambient;
lastDeclare = modifier
break;
case SyntaxKind.AsyncKeyword:
if (flags & NodeFlags.Async) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_already_seen, "async");
}
else if (flags & NodeFlags.Ambient || isInAmbientContext(node.parent)) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_be_used_in_an_ambient_context, "async");
}
else if (node.kind === SyntaxKind.Parameter) {
return grammarErrorOnNode(modifier, Diagnostics._0_modifier_cannot_appear_on_a_parameter, "async");
}
flags |= NodeFlags.Async;
lastAsync = modifier;
break;
}
}
@ -12294,16 +12677,42 @@ module ts {
else if (flags & NodeFlags.Private) {
return grammarErrorOnNode(lastPrivate, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "private");
}
else if (flags & NodeFlags.Async) {
return grammarErrorOnNode(lastAsync, Diagnostics._0_modifier_cannot_appear_on_a_constructor_declaration, "async");
}
return;
}
else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && flags & NodeFlags.Ambient) {
return grammarErrorOnNode(lastDeclare, Diagnostics.A_declare_modifier_cannot_be_used_with_an_import_declaration, "declare");
return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_import_declaration, "declare");
}
else if (node.kind === SyntaxKind.InterfaceDeclaration && flags & NodeFlags.Ambient) {
return grammarErrorOnNode(lastDeclare, Diagnostics.A_declare_modifier_cannot_be_used_with_an_interface_declaration, "declare");
return grammarErrorOnNode(lastDeclare, Diagnostics.A_0_modifier_cannot_be_used_with_an_interface_declaration, "declare");
}
else if (node.kind === SyntaxKind.Parameter && (flags & NodeFlags.AccessibilityModifier) && isBindingPattern((<ParameterDeclaration>node).name)) {
return grammarErrorOnNode(node, Diagnostics.A_parameter_property_may_not_be_a_binding_pattern);
}
if (flags & NodeFlags.Async) {
return checkGrammarAsyncModifier(node, lastAsync);
}
}
function checkGrammarAsyncModifier(node: Node, asyncModifier: Node): boolean {
if (languageVersion < ScriptTarget.ES6) {
return grammarErrorOnNode(asyncModifier, Diagnostics.Async_functions_are_only_available_when_targeting_ECMAScript_6_and_higher);
}
switch (node.kind) {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
if (!(<FunctionLikeDeclaration>node).asteriskToken) {
return false;
}
break;
}
return grammarErrorOnNode(asyncModifier, Diagnostics._0_modifier_cannot_be_used_here, "async");
}
function checkGrammarForDisallowedTrailingComma(list: NodeArray<Node>): boolean {

View file

@ -34,8 +34,12 @@ module ts {
Statements_are_not_allowed_in_ambient_contexts: { code: 1036, category: DiagnosticCategory.Error, key: "Statements are not allowed in ambient contexts." },
A_declare_modifier_cannot_be_used_in_an_already_ambient_context: { code: 1038, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used in an already ambient context." },
Initializers_are_not_allowed_in_ambient_contexts: { code: 1039, category: DiagnosticCategory.Error, key: "Initializers are not allowed in ambient contexts." },
_0_modifier_cannot_be_used_in_an_ambient_context: { code: 1040, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used in an ambient context." },
_0_modifier_cannot_be_used_with_a_class_declaration: { code: 1041, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a class declaration." },
_0_modifier_cannot_be_used_here: { code: 1042, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used here." },
_0_modifier_cannot_appear_on_a_data_property: { code: 1043, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a data property." },
_0_modifier_cannot_appear_on_a_module_element: { code: 1044, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot appear on a module element." },
A_declare_modifier_cannot_be_used_with_an_interface_declaration: { code: 1045, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an interface declaration." },
A_0_modifier_cannot_be_used_with_an_interface_declaration: { code: 1045, category: DiagnosticCategory.Error, key: "A '{0}' modifier cannot be used with an interface declaration." },
A_declare_modifier_is_required_for_a_top_level_declaration_in_a_d_ts_file: { code: 1046, category: DiagnosticCategory.Error, key: "A 'declare' modifier is required for a top level declaration in a .d.ts file." },
A_rest_parameter_cannot_be_optional: { code: 1047, category: DiagnosticCategory.Error, key: "A rest parameter cannot be optional." },
A_rest_parameter_cannot_have_an_initializer: { code: 1048, category: DiagnosticCategory.Error, key: "A rest parameter cannot have an initializer." },
@ -45,11 +49,13 @@ module ts {
A_set_accessor_cannot_have_rest_parameter: { code: 1053, category: DiagnosticCategory.Error, key: "A 'set' accessor cannot have rest parameter." },
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." },
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." },
Unexpected_token_A_constructor_method_accessor_or_property_was_expected: { code: 1068, category: DiagnosticCategory.Error, key: "Unexpected token. A constructor, method, accessor, or property was expected." },
A_declare_modifier_cannot_be_used_with_an_import_declaration: { code: 1079, category: DiagnosticCategory.Error, key: "A 'declare' modifier cannot be used with an import declaration." },
A_0_modifier_cannot_be_used_with_an_import_declaration: { code: 1079, category: DiagnosticCategory.Error, key: "A '{0}' modifier cannot be used with an import declaration." },
Invalid_reference_directive_syntax: { code: 1084, category: DiagnosticCategory.Error, key: "Invalid 'reference' directive syntax." },
Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher: { code: 1085, category: DiagnosticCategory.Error, key: "Octal literals are not available when targeting ECMAScript 5 and higher." },
An_accessor_cannot_be_declared_in_an_ambient_context: { code: 1086, category: DiagnosticCategory.Error, key: "An accessor cannot be declared in an ambient context." },
@ -120,7 +126,7 @@ module ts {
Unterminated_template_literal: { code: 1160, category: DiagnosticCategory.Error, key: "Unterminated template literal." },
Unterminated_regular_expression_literal: { code: 1161, category: DiagnosticCategory.Error, key: "Unterminated regular expression literal." },
An_object_member_cannot_be_declared_optional: { code: 1162, category: DiagnosticCategory.Error, key: "An object member cannot be declared optional." },
yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained_within a generator declaration." },
yield_expression_must_be_contained_within_a_generator_declaration: { code: 1163, category: DiagnosticCategory.Error, key: "'yield' expression must be contained within a generator declaration." },
Computed_property_names_are_not_allowed_in_enums: { code: 1164, category: DiagnosticCategory.Error, key: "Computed property names are not allowed in enums." },
A_computed_property_name_in_an_ambient_context_must_directly_refer_to_a_built_in_symbol: { code: 1165, category: DiagnosticCategory.Error, key: "A computed property name in an ambient context must directly refer to a built-in symbol." },
A_computed_property_name_in_a_class_property_declaration_must_directly_refer_to_a_built_in_symbol: { code: 1166, category: DiagnosticCategory.Error, key: "A computed property name in a class property declaration must directly refer to a built-in symbol." },
@ -174,6 +180,18 @@ module ts {
Type_expected_0_is_a_reserved_word_in_strict_mode: { code: 1215, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode" },
Type_expected_0_is_a_reserved_word_in_strict_mode_Class_definitions_are_automatically_in_strict_mode: { code: 1216, category: DiagnosticCategory.Error, key: "Type expected. '{0}' is a reserved word in strict mode. Class definitions are automatically in strict mode." },
Export_assignment_is_not_supported_when_module_flag_is_system: { code: 1218, category: DiagnosticCategory.Error, key: "Export assignment is not supported when '--module' flag is 'system'." },
with_statements_are_not_allowed_in_an_async_function_block: { code: 1300, category: DiagnosticCategory.Error, key: "'with' statements are not allowed in an async function block." },
_0_modifier_cannot_be_used_with_a_generator: { code: 1301, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a generator." },
_0_modifier_cannot_be_used_with_a_module_declaration: { code: 1302, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a module declaration." },
_0_modifier_cannot_be_used_with_an_enum_declaration: { code: 1303, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with an enum declaration." },
_0_modifier_cannot_be_used_with_an_export_assignment_declaration: { code: 1304, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with an export assignment declaration." },
_0_modifier_cannot_be_used_on_a_variable_statement: { code: 1305, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used on a variable statement." },
_0_modifier_cannot_be_used_with_a_type_declaration: { code: 1306, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a type declaration." },
_0_modifier_cannot_be_used_with_a_parameter_declaration: { code: 1307, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used with a parameter declaration." },
await_expression_must_be_contained_within_an_async_function: { code: 1308, category: DiagnosticCategory.Error, key: "'await' expression must be contained within an async function." },
_0_modifier_cannot_be_used_on_an_object_literal_element: { code: 1309, category: DiagnosticCategory.Error, key: "'{0}' modifier cannot be used on an object literal element." },
_0_expression_is_not_allowed_in_an_initializer: { code: 1310, category: DiagnosticCategory.Error, key: "'{0}' expression is not allowed in an initializer." },
Async_functions_are_only_available_when_targeting_ECMAScript_6_and_higher: { code: 1311, category: DiagnosticCategory.Error, key: "Async functions are only available when targeting ECMAScript 6 and higher." },
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
@ -363,6 +381,10 @@ 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." },
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." },
Duplicate_identifier_arguments_Compiler_uses_variable_declaration_arguments_to_capture_arguments_reference: { code: 2522, category: DiagnosticCategory.Error, key: "Duplicate identifier '_arguments'. Compiler uses variable declaration '_arguments' to capture 'arguments' reference." },
Expression_resolves_to_variable_declaration_arguments_that_compiler_uses_to_capture_arguments_reference: { code: 2523, category: DiagnosticCategory.Error, key: "Expression resolves to variable declaration '_arguments' that compiler uses to capture 'arguments' reference." },
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}'." },
@ -505,6 +527,7 @@ module ts {
Specifies_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix: { code: 6060, category: DiagnosticCategory.Message, key: "Specifies the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix)." },
NEWLINE: { code: 6061, category: DiagnosticCategory.Message, key: "NEWLINE" },
Argument_for_newLine_option_must_be_CRLF_or_LF: { code: 6062, category: DiagnosticCategory.Error, key: "Argument for '--newLine' option must be 'CRLF' or 'LF'." },
Emit_async_functions_when_ECMAScript_target_version_is_lower_than_ES6: { code: 6063, category: DiagnosticCategory.Message, key: "Emit async functions when ECMAScript target version is lower than 'ES6'." },
Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." },
Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." },
Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." },

View file

@ -123,11 +123,27 @@
"category": "Error",
"code": 1039
},
"'{0}' modifier cannot be used in an ambient context.": {
"category": "Error",
"code": 1040
},
"'{0}' modifier cannot be used with a class declaration.": {
"category": "Error",
"code": 1041
},
"'{0}' modifier cannot be used here.": {
"category": "Error",
"code": 1042
},
"'{0}' modifier cannot appear on a data property.": {
"category": "Error",
"code": 1043
},
"'{0}' modifier cannot appear on a module element.": {
"category": "Error",
"code": 1044
},
"A 'declare' modifier cannot be used with an interface declaration.": {
"A '{0}' modifier cannot be used with an interface declaration.": {
"category": "Error",
"code": 1045
},
@ -167,6 +183,14 @@
"category": "Error",
"code": 1056
},
"An async function or method must have a valid awaitable return type.": {
"category": "Error",
"code": 1057
},
"Type for 'await' does not have a valid callable 'then' member.": {
"category": "Error",
"code": 1058
},
"Enum member must have initializer.": {
"category": "Error",
"code": 1061
@ -183,7 +207,7 @@
"category": "Error",
"code": 1068
},
"A 'declare' modifier cannot be used with an import declaration.": {
"A '{0}' modifier cannot be used with an import declaration.": {
"category": "Error",
"code": 1079
},
@ -467,7 +491,7 @@
"category": "Error",
"code": 1162
},
"'yield' expression must be contained_within a generator declaration.": {
"'yield' expression must be contained within a generator declaration.": {
"category": "Error",
"code": 1163
},
@ -684,6 +708,55 @@
"code": 1218
},
"'with' statements are not allowed in an async function block.": {
"category": "Error",
"code": 1300
},
"'{0}' modifier cannot be used with a generator.": {
"category": "Error",
"code": 1301
},
"'{0}' modifier cannot be used with a module declaration.": {
"category": "Error",
"code": 1302
},
"'{0}' modifier cannot be used with an enum declaration.": {
"category": "Error",
"code": 1303
},
"'{0}' modifier cannot be used with an export assignment declaration.": {
"category": "Error",
"code": 1304
},
"'{0}' modifier cannot be used on a variable statement.": {
"category": "Error",
"code": 1305
},
"'{0}' modifier cannot be used with a type declaration.": {
"category": "Error",
"code": 1306
},
"'{0}' modifier cannot be used with a parameter declaration.": {
"category": "Error",
"code": 1307
},
"'await' expression must be contained within an async function.": {
"category": "Error",
"code": 1308
},
"'{0}' modifier cannot be used on an object literal element.": {
"category": "Error",
"code": 1309
},
"'{0}' expression is not allowed in an initializer.": {
"category": "Error",
"code": 1310
},
"Async functions are only available when targeting ECMAScript 6 and higher.": {
"category": "Error",
"code": 1311
},
"Duplicate identifier '{0}'.": {
"category": "Error",
"code": 2300
@ -1441,6 +1514,23 @@
"code": 2501
},
"Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions.": {
"category": "Error",
"code": 2520
},
"Expression resolves to variable declaration '{0}' that compiler uses to support async functions.": {
"category": "Error",
"code": 2521
},
"Duplicate identifier '_arguments'. Compiler uses variable declaration '_arguments' to capture 'arguments' reference.": {
"category": "Error",
"code": 2522
},
"Expression resolves to variable declaration '_arguments' that compiler uses to capture 'arguments' reference.": {
"category": "Error",
"code": 2523
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@ -2010,7 +2100,10 @@
"category": "Error",
"code": 6062
},
"Emit async functions when ECMAScript target version is lower than 'ES6'.": {
"category": "Message",
"code": 6063
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",

View file

@ -153,6 +153,8 @@ module ts {
case SyntaxKind.YieldExpression:
return visitNode(cbNode, (<YieldExpression>node).asteriskToken) ||
visitNode(cbNode, (<YieldExpression>node).expression);
case SyntaxKind.AwaitExpression:
return visitNode(cbNode, (<AwaitExpression>node).expression);
case SyntaxKind.PostfixUnaryExpression:
return visitNode(cbNode, (<PostfixUnaryExpression>node).operand);
case SyntaxKind.BinaryExpression:
@ -556,9 +558,17 @@ module ts {
function setDecoratorContext(val: boolean) {
setContextFlag(val, ParserContextFlags.Decorator);
}
function doOutsideOfContext<T>(flags: ParserContextFlags, func: () => T): T {
let currentContextFlags = contextFlags & flags;
function setAwaitContext(val: boolean) {
setContextFlag(val, ParserContextFlags.Await);
}
function setAsyncParameterContext(val: boolean) {
setContextFlag(val, ParserContextFlags.AsyncParameter);
}
function doOutsideOfContext<T>(context: ParserContextFlags, func: () => T): T {
let currentContextFlags = contextFlags & context;
if (currentContextFlags) {
setContextFlag(false, currentContextFlags);
let result = func();
@ -569,85 +579,86 @@ module ts {
// no need to do anything special as we are not in any of the requested contexts
return func();
}
function allowInAnd<T>(func: () => T): T {
if (contextFlags & ParserContextFlags.DisallowIn) {
setDisallowInContext(false);
function doInsideOfContext<T>(context: ParserContextFlags, func: () => T): T {
let unsetContextFlags = context & ~contextFlags;
if (!unsetContextFlags) {
setContextFlag(true, unsetContextFlags);
let result = func();
setDisallowInContext(true);
setContextFlag(false, unsetContextFlags);
return result;
}
// no need to do anything special if 'in' is already allowed.
// no need to do anything special as we are already in all of the requested contexts
return func();
}
function allowInAnd<T>(func: () => T): T {
return doInsideOfContext(ParserContextFlags.DisallowIn, func);
}
function disallowInAnd<T>(func: () => T): T {
if (contextFlags & ParserContextFlags.DisallowIn) {
// no need to do anything special if 'in' is already disallowed.
return func();
}
setDisallowInContext(true);
let result = func();
setDisallowInContext(false);
return result;
return doOutsideOfContext(ParserContextFlags.DisallowIn, func);
}
function doInYieldContext<T>(func: () => T): T {
if (contextFlags & ParserContextFlags.Yield) {
// no need to do anything special if we're already in the [Yield] context.
return func();
}
setYieldContext(true);
let result = func();
setYieldContext(false);
return result;
return doInsideOfContext(ParserContextFlags.Yield, func);
}
function doOutsideOfYieldContext<T>(func: () => T): T {
if (contextFlags & ParserContextFlags.Yield) {
setYieldContext(false);
let result = func();
setYieldContext(true);
return result;
}
// no need to do anything special if we're not in the [Yield] context.
return func();
return doOutsideOfContext(ParserContextFlags.Yield, func);
}
function doInDecoratorContext<T>(func: () => T): T {
if (contextFlags & ParserContextFlags.Decorator) {
// no need to do anything special if we're already in the [Decorator] context.
return func();
}
setDecoratorContext(true);
let result = func();
setDecoratorContext(false);
return result;
return doInsideOfContext(ParserContextFlags.Decorator, func);
}
function doInAwaitContext<T>(func: () => T): T {
return doInsideOfContext(ParserContextFlags.Await, func);
}
function doOutsideOfAwaitContext<T>(func: () => T): T {
return doOutsideOfContext(ParserContextFlags.Await, func);
}
function doOutsideOfYieldAndAwaitContext<T>(func: () => T): T {
return doOutsideOfContext(ParserContextFlags.Yield | ParserContextFlags.Await, func);
}
function inContext(flags: ParserContextFlags) {
return (contextFlags & flags) === flags;
}
function inYieldContext() {
return (contextFlags & ParserContextFlags.Yield) !== 0;
return inContext(ParserContextFlags.Yield);
}
function inStrictModeContext() {
return (contextFlags & ParserContextFlags.StrictMode) !== 0;
return inContext(ParserContextFlags.StrictMode);
}
function inGeneratorParameterContext() {
return (contextFlags & ParserContextFlags.GeneratorParameter) !== 0;
return inContext(ParserContextFlags.GeneratorParameter);
}
function inDisallowInContext() {
return (contextFlags & ParserContextFlags.DisallowIn) !== 0;
return inContext(ParserContextFlags.DisallowIn);
}
function inDecoratorContext() {
return (contextFlags & ParserContextFlags.Decorator) !== 0;
return inContext(ParserContextFlags.Decorator);
}
function inAwaitContext() {
return inContext(ParserContextFlags.Await);
}
function inAsyncParameterContext() {
return inContext(ParserContextFlags.AsyncParameter);
}
function inGeneratorParameterOrAsyncParameterContext() {
return inContext(ParserContextFlags.GeneratorParameter | ParserContextFlags.AsyncParameter);
}
function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): void {
@ -927,7 +938,8 @@ module ts {
// PropertyName[Yield,GeneratorParameter] :
// LiteralPropertyName
// [+GeneratorParameter] ComputedPropertyName
// [~GeneratorParameter] ComputedPropertyName[?Yield]
// [+AsyncParameter] ComputedPropertyName
// [~GeneratorParameter,~AsyncParameter] ComputedPropertyName[?Yield,?Await]
//
// ComputedPropertyName[Yield] :
// [ AssignmentExpression[In, ?Yield] ]
@ -938,34 +950,40 @@ module ts {
// We parse any expression (including a comma expression). But the grammar
// says that only an assignment expression is allowed, so the grammar checker
// will error if it sees a comma expression.
let yieldContext = inYieldContext();
if (inGeneratorParameterContext()) {
setYieldContext(false);
}
node.expression = allowInAnd(parseExpression);
if (inGeneratorParameterContext()) {
setYieldContext(yieldContext);
}
node.expression = inGeneratorParameterOrAsyncParameterContext()
? doOutsideOfYieldAndAwaitContext(parseExpression)
: parseExpression();
parseExpected(SyntaxKind.CloseBracketToken);
return finishNode(node);
}
function parseContextualModifier(t: SyntaxKind): boolean {
return token === t && tryParse(nextTokenCanFollowModifier);
function parseContextualModifier(t: SyntaxKind, isArrowFunction?: boolean): boolean {
return token === t && tryParse(isArrowFunction
? nextTokenCanFollowModifierForArrowFunction
: nextTokenCanFollowModifier);
}
function nextTokenCanFollowModifierForArrowFunction() {
return nextTokenCanFollowModifier(/*isArrowFunction*/ true);
}
function nextTokenCanFollowModifier() {
function nextTokenCanFollowModifier(isArrowFunction?: boolean) {
nextToken();
return canFollowModifier();
return canFollowModifier(isArrowFunction);
}
function parseAnyContextualModifier(): boolean {
return isModifier(token) && tryParse(nextTokenCanFollowContextualModifier);
function parseAnyContextualModifier(isArrowFunction?: boolean): boolean {
return isModifier(token) && tryParse(isArrowFunction
? nextTokenCanFollowContextualModifierForArrowFunction
: nextTokenCanFollowContextualModifier);
}
function nextTokenCanFollowContextualModifierForArrowFunction() {
return nextTokenCanFollowContextualModifier(/*isArrowFunction*/ true);
}
function nextTokenCanFollowContextualModifier() {
function nextTokenCanFollowContextualModifier(isArrowFunction?: boolean) {
if (token === SyntaxKind.ConstKeyword) {
// 'const' is only a modifier if followed by 'enum'.
return nextToken() === SyntaxKind.EnumKeyword;
@ -981,10 +999,19 @@ module ts {
return nextTokenIsClassOrFunction();
}
nextToken();
return canFollowModifier();
return canFollowModifier(isArrowFunction);
}
function canFollowModifier(): boolean {
function canFollowModifier(isArrowFunction?: boolean): boolean {
if (isArrowFunction) {
if (scanner.hasPrecedingLineBreak()) {
return false;
}
return token === SyntaxKind.OpenParenToken
|| token === SyntaxKind.LessThanToken;
}
return token === SyntaxKind.OpenBracketToken
|| token === SyntaxKind.OpenBraceToken
|| token === SyntaxKind.AsteriskToken
@ -1827,11 +1854,10 @@ module ts {
setModifiers(node, parseModifiers());
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
// SingleNameBinding[Yield,GeneratorParameter] : See 13.2.3
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
// FormalParameter[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 14.1
// BindingElement[?Yield,?GeneratorParameter,?Await,?AsyncParameter]
node.name = inGeneratorParameterContext() ? doInYieldContext(parseIdentifierOrPattern) : parseIdentifierOrPattern();
node.name = parseIdentifierOrPattern();
if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifier(token)) {
// in cases like
@ -1847,7 +1873,7 @@ module ts {
node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
node.type = parseParameterType();
node.initializer = inGeneratorParameterContext() ? doOutsideOfYieldContext(parseParameterInitializer) : parseParameterInitializer();
node.initializer = parseBindingElementInitializer(/*inParameter*/ true);
// Do not check for initializers in an ambient context for parameters. This is not
// a grammar error because the grammar allows arbitrary call signatures in
@ -1859,19 +1885,36 @@ module ts {
// ambient contexts.
return finishNode(node);
}
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,~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,~AsyncParameter] BindingIdentifier[?Yield,?Await] Initializer[In,?Yield,?Await]opt
let parseInitializer = inParameter ? parseParameterInitializer : parseNonParameterInitializer;
return inGeneratorParameterOrAsyncParameterContext()
? doOutsideOfYieldAndAwaitContext(parseInitializer)
: parseInitializer();
}
function parseParameterInitializer() {
return parseInitializer(/*inParameter*/ true);
}
function fillSignature(
returnToken: SyntaxKind,
yieldAndGeneratorParameterContext: boolean,
awaitAndAsyncParameterContext: boolean,
requireCompleteParameterList: boolean,
signature: SignatureDeclaration): void {
let returnTokenRequired = returnToken === SyntaxKind.EqualsGreaterThanToken;
signature.typeParameters = parseTypeParameters();
signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, requireCompleteParameterList);
signature.parameters = parseParameterList(yieldAndGeneratorParameterContext, awaitAndAsyncParameterContext, requireCompleteParameterList);
if (returnTokenRequired) {
parseExpected(returnToken);
@ -1886,32 +1929,48 @@ module ts {
// have 'Yield' And 'GeneratorParameter' not in sync. i.e. any production calling
// this FormalParameters production either always sets both to true, or always sets
// both to false. As such we only have a single parameter to represent both.
function parseParameterList(yieldAndGeneratorParameterContext: boolean, requireCompleteParameterList: boolean) {
// FormalParameters[Yield,GeneratorParameter] :
function parseParameterList(yieldAndGeneratorParameterContext: boolean, awaitAndAsyncParameterContext: boolean, requireCompleteParameterList: boolean) {
// FormalParameters[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified)
// ...
//
// FormalParameter[Yield,GeneratorParameter] :
// BindingElement[?Yield, ?GeneratorParameter]
// FormalParameter[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified)
// BindingElement[?Yield,?GeneratorParameter,?Await,?AsyncParameter]
//
// BindingElement[Yield, GeneratorParameter ] : See 13.2.3
// SingleNameBinding[?Yield, ?GeneratorParameter]
// [+GeneratorParameter]BindingPattern[?Yield, GeneratorParameter]Initializer[In]opt
// [~GeneratorParameter]BindingPattern[?Yield]Initializer[In, ?Yield]opt
// BindingElement[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 13.2.3
// SingleNameBinding[?Yield,?GeneratorParameter,?Await,?AsyncParameter]
// [+GeneratorParameter]BindingPattern[?Yield,?Await,?AsyncParameter,GeneratorParameter] Initializer[In]opt
// [+AsyncParameter]BindingPattern[?Yield,?Await,?GeneratorParameter,AsyncParameter] Initializer[In]opt
// [~GeneratorParameter,~AsyncParameter]BindingPattern[?Yield,?Await]Initializer[In,?Yield,?Await]opt
//
// SingleNameBinding[Yield, GeneratorParameter] : See 13.2.3
// SingleNameBinding[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 13.2.3
// [+GeneratorParameter]BindingIdentifier[Yield]Initializer[In]opt
// [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
// [+AsyncParameter]BindingIdentifier[Await]Initializer[In]opt
// [~GeneratorParameter,~AsyncParameter]BindingIdentifier[?Yield,?Await]Initializer[In,?Yield,?Await]opt
if (parseExpected(SyntaxKind.OpenParenToken)) {
let savedYieldContext = inYieldContext();
let savedGeneratorParameterContext = inGeneratorParameterContext();
let savedAwaitContext = inAwaitContext();
let savedAsyncParameterContext = inAsyncParameterContext();
setYieldContext(yieldAndGeneratorParameterContext);
if (yieldAndGeneratorParameterContext) {
setYieldContext(true);
}
setGeneratorParameterContext(yieldAndGeneratorParameterContext);
if (awaitAndAsyncParameterContext) {
setAwaitContext(true);
}
setAsyncParameterContext(awaitAndAsyncParameterContext);
let result = parseDelimitedList(ParsingContext.Parameters, parseParameter);
setYieldContext(savedYieldContext);
setGeneratorParameterContext(savedGeneratorParameterContext);
setAwaitContext(savedAwaitContext);
setAsyncParameterContext(savedAsyncParameterContext);
if (!parseExpected(SyntaxKind.CloseParenToken) && requireCompleteParameterList) {
// Caller insisted that we had to end with a ) We didn't. So just return
@ -1944,7 +2003,7 @@ module ts {
if (kind === SyntaxKind.ConstructSignature) {
parseExpected(SyntaxKind.NewKeyword);
}
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList:*/ false, node);
parseTypeMemberSemicolon();
return finishNode(node);
}
@ -2034,7 +2093,7 @@ module ts {
// Method signatues don't exist in expression contexts. So they have neither
// [Yield] nor [GeneratorParameter]
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, method);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList:*/ false, method);
parseTypeMemberSemicolon();
return finishNode(method);
}
@ -2173,7 +2232,7 @@ module ts {
if (kind === SyntaxKind.ConstructorType) {
parseExpected(SyntaxKind.NewKeyword);
}
fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
fillSignature(SyntaxKind.EqualsGreaterThanToken, /*yieldAndGeneratorParameterContext:*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList:*/ false, node);
return finishNode(node);
}
@ -2302,19 +2361,8 @@ module ts {
function parseType(): TypeNode {
// The rules about 'yield' only apply to actual code/expression contexts. They don't
// apply to 'type' contexts. So we disable these parameters here before moving on.
let savedYieldContext = inYieldContext();
let savedGeneratorParameterContext = inGeneratorParameterContext();
setYieldContext(false);
setGeneratorParameterContext(false);
let result = parseTypeWorker();
setYieldContext(savedYieldContext);
setGeneratorParameterContext(savedGeneratorParameterContext);
return result;
// apply to 'type' contexts. So we disable these parameters here before moving on.
return doOutsideOfContext(ParserContextFlags.ContextParameterFlags, parseTypeWorker);
}
function parseTypeWorker(): TypeNode {
@ -2374,6 +2422,7 @@ module ts {
case SyntaxKind.PlusPlusToken:
case SyntaxKind.MinusMinusToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.AwaitKeyword:
case SyntaxKind.YieldKeyword:
// Yield 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
@ -2586,7 +2635,7 @@ module ts {
node.parameters.end = parameter.end;
node.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, false, Diagnostics._0_expected, "=>");
node.body = parseArrowFunctionExpressionBody();
node.body = parseArrowFunctionExpressionBody(/*isAsync*/ false);
return finishNode(node);
}
@ -2617,7 +2666,7 @@ module ts {
var lastToken = token;
arrowFunction.equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken, /*reportAtCurrentPosition:*/false, Diagnostics._0_expected, "=>");
arrowFunction.body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken)
? parseArrowFunctionExpressionBody()
? parseArrowFunctionExpressionBody(/*isAsync*/ isAsyncFunctionLike(arrowFunction))
: parseIdentifier();
return finishNode(arrowFunction);
@ -2628,7 +2677,7 @@ module ts {
// Unknown -> There *might* be a parenthesized arrow function here.
// Speculatively look ahead to be sure, and rollback if not.
function isParenthesizedArrowFunctionExpression(): Tristate {
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken || token === SyntaxKind.AsyncKeyword) {
return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
}
@ -2643,6 +2692,10 @@ module ts {
}
function isParenthesizedArrowFunctionExpressionWorker() {
if (token === SyntaxKind.AsyncKeyword && !parseContextualModifier(SyntaxKind.AsyncKeyword, /*isArrowFunction*/ true)) {
return Tristate.False;
}
let first = token;
let second = nextToken();
@ -2718,6 +2771,9 @@ module ts {
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): ArrowFunction {
let node = <ArrowFunction>createNode(SyntaxKind.ArrowFunction);
setModifiers(node, parseModifiers(/*isArrowFunction*/ true));
let isAsync = isAsyncFunctionLike(node);
// Arrow functions are never generators.
//
// If we're speculatively parsing a signature for a parenthesized arrow function, then
@ -2725,7 +2781,7 @@ module ts {
// a => (b => c)
// And think that "(b =>" was actually a parenthesized arrow function with a missing
// close paren.
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ !allowAmbiguity, node);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList:*/ !allowAmbiguity, node);
// If we couldn't get parameters, we definitely could not parse out an arrow function.
if (!node.parameters) {
@ -2748,9 +2804,9 @@ module ts {
return node;
}
function parseArrowFunctionExpressionBody(): Block | Expression {
function parseArrowFunctionExpressionBody(isAsync: boolean): Block | Expression {
if (token === SyntaxKind.OpenBraceToken) {
return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false);
return parseFunctionBlock(/*allowYield*/ false, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false);
}
if (isStartOfStatement(/*inErrorRecovery:*/ true) &&
@ -2772,10 +2828,12 @@ module ts {
// up preemptively closing the containing construct.
//
// Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error.
return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ true);
return parseFunctionBlock(/*allowYield*/ false, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ true);
}
return parseAssignmentExpressionOrHigher();
return isAsync
? doInAwaitContext(parseAssignmentExpressionOrHigher)
: doOutsideOfAwaitContext(parseAssignmentExpressionOrHigher);
}
function parseConditionalExpressionRest(leftOperand: Expression): Expression {
@ -2915,8 +2973,32 @@ module ts {
node.expression = parseUnaryExpressionOrHigher();
return finishNode(node);
}
function isAwaitExpression(): boolean {
if (token === SyntaxKind.AwaitKeyword) {
if (inAwaitContext()) {
return true;
}
// here we are using similar heuristics as 'isYieldExpression'
return lookAhead(nextTokenIsIdentifierOnSameLine);
}
return false;
}
function parseAwaitExpression() {
var node = <AwaitExpression>createNode(SyntaxKind.AwaitExpression);
nextToken();
node.expression = parseUnaryExpressionOrHigher();
return finishNode(node);
}
function parseUnaryExpressionOrHigher(): UnaryExpression {
if (isAwaitExpression()) {
return parseAwaitExpression();
}
switch (token) {
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
@ -3230,6 +3312,11 @@ module ts {
return parseArrayLiteralExpression();
case SyntaxKind.OpenBraceToken:
return parseObjectLiteralExpression();
case SyntaxKind.AsyncKeyword:
if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
break;
}
return parseFunctionExpression();
case SyntaxKind.ClassKeyword:
return parseClassExpression();
case SyntaxKind.FunctionKeyword:
@ -3353,15 +3440,32 @@ module ts {
if (saveDecoratorContext) {
setDecoratorContext(false);
}
let node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression);
setModifiers(node, parseModifiers());
parseExpected(SyntaxKind.FunctionKeyword);
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node);
node.body = parseFunctionBlock(/*allowYield:*/ !!node.asteriskToken, /* ignoreMissingOpenBrace */ false);
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
let savedYieldContext = inYieldContext();
let isGenerator = node.asteriskToken != undefined;
setYieldContext(isGenerator);
let savedAwaitContext = inAwaitContext();
let isAsync = isAsyncFunctionLike(node);
setAwaitContext(isAsync);
node.name = parseOptionalIdentifier();
setYieldContext(savedYieldContext);
setAwaitContext(savedAwaitContext);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ isGenerator, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList*/ false, node);
node.body = parseFunctionBlock(/*allowYield*/ isGenerator, /*allowAwait*/ isAsync, /*ignoreMissingOpenBrace*/ false);
if (saveDecoratorContext) {
setDecoratorContext(true);
}
return finishNode(node);
}
@ -3394,9 +3498,12 @@ module ts {
return finishNode(node);
}
function parseFunctionBlock(allowYield: boolean, ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
function parseFunctionBlock(allowYield: boolean, allowAwait: boolean, ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
let savedYieldContext = inYieldContext();
setYieldContext(allowYield);
let savedAwaitContext = inAwaitContext();
setAwaitContext(allowAwait);
// We may be in a [Decorator] context when parsing a function expression or
// arrow function. The body of the function is not in [Decorator] context.
@ -3412,6 +3519,7 @@ module ts {
}
setYieldContext(savedYieldContext);
setAwaitContext(savedAwaitContext);
return block;
}
@ -3702,6 +3810,15 @@ module ts {
// In ES 6 'enum' is a future reserved keyword, so it should not be used as identifier
let isConstEnum = lookAhead(nextTokenIsEnumKeyword);
return !isConstEnum;
case SyntaxKind.AsyncKeyword:
// When followed by the function keyword on the same line, this is a statement
if (lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
return true;
}
return isStartOfExpression();
case SyntaxKind.InterfaceKeyword:
case SyntaxKind.ModuleKeyword:
case SyntaxKind.NamespaceKeyword:
@ -3835,13 +3952,13 @@ module ts {
return undefined;
}
function parseFunctionBlockOrSemicolon(isGenerator: boolean, diagnosticMessage?: DiagnosticMessage): Block {
function parseFunctionBlockOrSemicolon(isGenerator: boolean, isAsync: boolean, diagnosticMessage?: DiagnosticMessage): Block {
if (token !== SyntaxKind.OpenBraceToken && canParseSemicolon()) {
parseSemicolon();
return;
}
return parseFunctionBlock(isGenerator, /*ignoreMissingOpenBrace:*/ false, diagnosticMessage);
return parseFunctionBlock(isGenerator, isAsync, /*ignoreMissingOpenBrace:*/ false, diagnosticMessage);
}
// DECLARATIONS
@ -3853,7 +3970,7 @@ module ts {
let node = <BindingElement>createNode(SyntaxKind.BindingElement);
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
node.name = parseIdentifierOrPattern();
node.initializer = parseInitializer(/*inParameter*/ false);
node.initializer = parseBindingElementInitializer(/*inParameter*/ false);
return finishNode(node);
}
@ -3870,7 +3987,7 @@ module ts {
node.propertyName = <Identifier>propertyName;
node.name = parseIdentifierOrPattern();
}
node.initializer = parseInitializer(/*inParameter*/ false);
node.initializer = parseBindingElementInitializer(/*inParameter*/ false);
return finishNode(node);
}
@ -3976,8 +4093,10 @@ module ts {
parseExpected(SyntaxKind.FunctionKeyword);
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
node.name = node.flags & NodeFlags.Default ? parseOptionalIdentifier() : parseIdentifier();
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, /*requireCompleteParameterList:*/ false, node);
node.body = parseFunctionBlockOrSemicolon(!!node.asteriskToken, Diagnostics.or_expected);
let isGenerator = node.asteriskToken != undefined;
let isAsync = isAsyncFunctionLike(node);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ isGenerator, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList:*/ false, node);
node.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, Diagnostics.or_expected);
return finishNode(node);
}
@ -3986,8 +4105,8 @@ module ts {
node.decorators = decorators;
setModifiers(node, modifiers);
parseExpected(SyntaxKind.ConstructorKeyword);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false, Diagnostics.or_expected);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList*/ false, node);
node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false, Diagnostics.or_expected);
return finishNode(node);
}
@ -3998,8 +4117,10 @@ module ts {
method.asteriskToken = asteriskToken;
method.name = name;
method.questionToken = questionToken;
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!asteriskToken, /*requireCompleteParameterList:*/ false, method);
method.body = parseFunctionBlockOrSemicolon(!!asteriskToken, diagnosticMessage);
let isGenerator = asteriskToken != undefined;
let isAsync = isAsyncFunctionLike(method);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ isGenerator, /*awaitAndAsyncParameterContext*/ isAsync, /*requireCompleteParameterList:*/ false, method);
method.body = parseFunctionBlockOrSemicolon(isGenerator, isAsync, diagnosticMessage);
return finishNode(method);
}
@ -4039,8 +4160,8 @@ module ts {
node.decorators = decorators;
setModifiers(node, modifiers);
node.name = parsePropertyName();
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, /*requireCompleteParameterList:*/ false, node);
node.body = parseFunctionBlockOrSemicolon(/*isGenerator:*/ false);
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext*/ false, /*awaitAndAsyncParameterContext*/ false, /*requireCompleteParameterList*/ false, node);
node.body = parseFunctionBlockOrSemicolon(/*isGenerator*/ false, /*isAsync*/ false);
return finishNode(node);
}
@ -4147,14 +4268,14 @@ module ts {
return decorators;
}
function parseModifiers(): ModifiersArray {
function parseModifiers(isArrowFunction?: boolean): ModifiersArray {
let flags = 0;
let modifiers: ModifiersArray;
while (true) {
let modifierStart = scanner.getStartPos();
let modifierKind = token;
if (!parseAnyContextualModifier()) {
if (!parseAnyContextualModifier(isArrowFunction)) {
break;
}
@ -4228,7 +4349,7 @@ module ts {
function parseClassDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray): ClassDeclaration {
return <ClassDeclaration>parseClassDeclarationOrExpression(fullStart, decorators, modifiers, SyntaxKind.ClassDeclaration);
}
function parseClassDeclarationOrExpression(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, kind: SyntaxKind): ClassLikeDeclaration {
// In ES6 specification, All parts of a ClassDeclaration or a ClassExpression are strict mode code
let savedStrictModeContext = inStrictModeContext();
@ -4243,13 +4364,15 @@ module ts {
node.heritageClauses = parseHeritageClauses(/*isClassHeritageClause:*/ true);
if (parseExpected(SyntaxKind.OpenBraceToken)) {
// ClassTail[Yield,GeneratorParameter] : See 14.5
// [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
// ClassTail[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 14.5
// [~GeneratorParameter,~AsyncParameter]ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
// [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
node.members = inGeneratorParameterContext()
? doOutsideOfYieldContext(parseClassMembers)
// [+AsyncParameter] ClassHeritageopt { ClassBodyopt }
node.members = inGeneratorParameterOrAsyncParameterContext()
? doOutsideOfYieldAndAwaitContext(parseClassMembers)
: parseClassMembers();
parseExpected(SyntaxKind.CloseBraceToken);
}
else {
@ -4262,13 +4385,14 @@ module ts {
}
function parseHeritageClauses(isClassHeritageClause: boolean): NodeArray<HeritageClause> {
// ClassTail[Yield,GeneratorParameter] : See 14.5
// [~GeneratorParameter]ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
// ClassTail[Yield,GeneratorParameter,Await,AsyncParameter] : (Modified) See 14.5
// [~GeneratorParameter,~AsyncParameter]ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
// [+GeneratorParameter] ClassHeritageopt { ClassBodyopt }
// [+AsyncParameter] ClassHeritageopt { ClassBodyopt }
if (isHeritageClause()) {
return isClassHeritageClause && inGeneratorParameterContext()
? doOutsideOfYieldContext(parseHeritageClausesWorker)
return isClassHeritageClause && inGeneratorParameterOrAsyncParameterContext()
? doOutsideOfYieldAndAwaitContext(parseHeritageClausesWorker)
: parseHeritageClausesWorker();
}
@ -4652,6 +4776,11 @@ module ts {
case SyntaxKind.StaticKeyword:
// Check for modifier on source element
return lookAhead(nextTokenIsDeclarationStart);
case SyntaxKind.AsyncKeyword:
// Check for modifier on source element
return lookAhead(nextTokenIsDeclarationStartOnSameLine);
case SyntaxKind.AtToken:
// a lookahead here is too costly, and decorators are only valid on a declaration.
// We will assume we are parsing a declaration here and report an error later
@ -4690,6 +4819,16 @@ module ts {
return isDeclarationStart(/*followsModifier*/ true);
}
function nextTokenIsDeclarationStartOnSameLine() {
nextToken();
return !scanner.hasPrecedingLineBreak() && isDeclarationStart();
}
function nextTokenIsFunctionKeywordOnSameLine() {
nextToken();
return !scanner.hasPrecedingLineBreak() && token === SyntaxKind.FunctionKeyword;
}
function nextTokenIsAsKeyword() {
return nextToken() === SyntaxKind.AsKeyword;
}

View file

@ -101,6 +101,8 @@ module ts {
"while": SyntaxKind.WhileKeyword,
"with": SyntaxKind.WithKeyword,
"yield": SyntaxKind.YieldKeyword,
"async": SyntaxKind.AsyncKeyword,
"await": SyntaxKind.AwaitKeyword,
"of": SyntaxKind.OfKeyword,
"{": SyntaxKind.OpenBraceToken,
"}": SyntaxKind.CloseBraceToken,

View file

@ -133,6 +133,8 @@ module ts {
// Contextual keywords
AsKeyword,
AnyKeyword,
AsyncKeyword,
AwaitKeyword,
BooleanKeyword,
ConstructorKeyword,
DeclareKeyword,
@ -197,6 +199,7 @@ module ts {
DeleteExpression,
TypeOfExpression,
VoidExpression,
AwaitExpression,
PrefixUnaryExpression,
PostfixUnaryExpression,
BinaryExpression,
@ -316,8 +319,9 @@ module ts {
OctalLiteral = 0x00004000, // Octal numeric literal
Namespace = 0x00008000, // Namespace declaration
ExportContext = 0x00010000, // Export context (initialized by binding)
Async = 0x00020000, // Property/Method/Function
Modifier = Export | Ambient | Public | Private | Protected | Static | Default,
Modifier = Export | Ambient | Public | Private | Protected | Static | Default | Async,
AccessibilityModifier = Public | Private | Protected,
BlockScoped = Let | Const
}
@ -345,17 +349,29 @@ module ts {
// error.
ThisNodeHasError = 1 << 5,
// Context flags set directly by the parser.
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError,
// 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,
// Context flags set directly by the parser.
ParserGeneratedFlags = StrictMode | DisallowIn | Yield | GeneratorParameter | Decorator | ThisNodeHasError | AsyncParameter | Await,
// Context flags passed as part of the modified ES6 grammar.
ContextParameterFlags = Yield | GeneratorParameter | AsyncParameter | Await,
// Context flags computed by aggregating child flags upwards.
// Used during incremental parsing to determine if this node or any of its children had an
// error. Computed only once and then cached.
ThisNodeOrAnySubNodesHasError = 1 << 6,
ThisNodeOrAnySubNodesHasError = 1 << 8,
// Used to know if we've computed whether any children of this node are or contain an 'await' or 'yield' expression.
ThisNodeOrAnySubNodesHasAwaitOrYield = 1 << 9,
// Used to know if we've computed data from children and cached it in this node.
HasAggregatedChildData = 1 << 7
HasAggregatedChildData = 1 << 10
}
/* @internal */
@ -658,6 +674,10 @@ module ts {
expression: UnaryExpression;
}
export interface AwaitExpression extends UnaryExpression {
expression: UnaryExpression;
}
export interface YieldExpression extends Expression {
asteriskToken?: Node;
expression: Expression;
@ -1403,22 +1423,28 @@ module ts {
TypeChecked = 0x00000001, // Node has been type checked
LexicalThis = 0x00000002, // Lexical 'this' reference
CaptureThis = 0x00000004, // Lexical 'this' used in body
EmitExtends = 0x00000008, // Emit __extends
SuperInstance = 0x00000010, // Instance 'super' reference
SuperStatic = 0x00000020, // Static 'super' reference
ContextChecked = 0x00000040, // Contextual types have been assigned
LexicalArguments = 0x00000008, // Lexical 'arguments' reference
CaptureArguments = 0x00000010, // Lexical 'arguments' used in body
EmitExtends = 0x00000020, // Emit __extends
EmitDecorate = 0x00000040, // Emit __decorate
EmitParam = 0x00000080, // Emit __param helper for decorators
EmitAwaiter = 0x00000100, // Emit __awaiter
EmitGenerator = 0x00000200, // Emit __generator
SuperInstance = 0x00000400, // Instance 'super' reference
SuperStatic = 0x00000800, // Static 'super' reference
ContextChecked = 0x00001000, // Contextual types have been assigned
PromiseCollision = 0x00002000, // Declaration collides with the global 'Promise'
// Values for enum members have been computed, and any errors have been reported for them.
EnumValuesComputed = 0x00000080,
BlockScopedBindingInLoop = 0x00000100,
EmitDecorate = 0x00000200, // Emit __decorate
EmitParam = 0x00000400, // Emit __param helper for decorators
LexicalModuleMergesWithClass = 0x00000800, // Instantiated lexical module declaration is merged with a previous class declaration.
EnumValuesComputed = 0x00004000,
BlockScopedBindingInLoop = 0x00008000,
LexicalModuleMergesWithClass= 0x00010000, // Instantiated lexical module declaration is merged with a previous class declaration.
}
/* @internal */
export interface NodeLinks {
resolvedType?: Type; // Cached type of type node
resolvedAwaitedType?: Type; // Cached awaited type of type node
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSymbol?: Symbol; // Cached name resolution result
flags?: NodeCheckFlags; // Set of flags specific to Node

View file

@ -511,6 +511,19 @@ module ts {
}
}
export function getContainingParameter(node: Node): ParameterDeclaration {
while (true) {
node = node.parent;
if (!node || isFunctionLike(node)) {
return undefined;
}
if (node.kind === SyntaxKind.Parameter) {
return <ParameterDeclaration>node;
}
}
}
export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node {
while (true) {
node = node.parent;
@ -1087,6 +1100,10 @@ module ts {
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
}
export function isAsyncFunctionLike(node: Node): boolean {
return isFunctionLike(node) && !isAccessor(node) && (node.flags & NodeFlags.Async) === NodeFlags.Async;
}
/**
* A declaration has a dynamic name if both of the following are true:
* 1. The declaration has a computed property name
@ -1145,6 +1162,7 @@ module ts {
case SyntaxKind.DeclareKeyword:
case SyntaxKind.ConstKeyword:
case SyntaxKind.DefaultKeyword:
case SyntaxKind.AsyncKeyword:
return true;
}
return false;
@ -1630,6 +1648,7 @@ module ts {
case SyntaxKind.DeclareKeyword: return NodeFlags.Ambient;
case SyntaxKind.ConstKeyword: return NodeFlags.Const;
case SyntaxKind.DefaultKeyword: return NodeFlags.Default;
case SyntaxKind.AsyncKeyword: return NodeFlags.Async;
}
return 0;
}

12
src/lib/core.d.ts vendored
View file

@ -1169,3 +1169,15 @@ declare type ClassDecorator = <TFunction extends Function>(target: TFunction) =>
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
declare type PromiseConstructorLike = new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) => PromiseLike<T>;
interface PromiseLike<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
}

10
src/lib/es6.d.ts vendored
View file

@ -3572,16 +3572,6 @@ declare module Reflect {
function setPrototypeOf(target: any, proto: any): boolean;
}
interface PromiseLike<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
}
/**
* Represents the completion of an asynchronous operation
*/