diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8e89eb51343..c1fe11dc638 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6710,6 +6710,19 @@ module ts { } function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) { + // Grammar checking + if (!checkGrammarModifiers(node)) { + if (node.parserContextFlags & ParserContextFlags.StrictMode) { + if (isLeftHandSideExpression(node.left) && isAssignmentOperator(node.operator)) { + if (isEvalOrArgumentsIdentifier(node.left)) { + // ECMA 262 (Annex C) The identifier eval or arguments may not appear as the LeftHandSideExpression of an + // Assignment operator(11.13) or of a PostfixExpression(11.3) + reportGrammarErrorOfInvalidUseInStrictMode(node.left); + } + } + } + } + var operator = node.operator; if (operator === SyntaxKind.EqualsToken && (node.left.kind === SyntaxKind.ObjectLiteralExpression || node.left.kind === SyntaxKind.ArrayLiteralExpression)) { return checkDestructuringAssignment(node.left, checkExpression(node.right, contextualMapper), contextualMapper); @@ -9950,6 +9963,13 @@ module ts { } } + function reportGrammarErrorOfInvalidUseInStrictMode(node: Identifier): boolean { + // declarationNameToString cannot be used here since it uses a backreference to 'parent' that is not yet set + var sourceText = getSourceFileOfNode(node).text; + var name = sourceText.substring(skipTrivia(sourceText, node.pos), node.end); + return grammarErrorOnNode(node, Diagnostics.Invalid_use_of_0_in_strict_mode, name); + } + initializeTypeChecker(); return checker; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a07b9856d70..c1ebc5abd4e 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -178,7 +178,7 @@ module ts { return node.kind === SyntaxKind.ExpressionStatement && (node).expression.kind === SyntaxKind.StringLiteral; } - function isEvalOrArgumentsIdentifier(node: Node): boolean { + export function isEvalOrArgumentsIdentifier(node: Node): boolean { return node.kind === SyntaxKind.Identifier && (node).text && ((node).text === "eval" || (node).text === "arguments"); @@ -4533,7 +4533,7 @@ module ts { } } - function isLeftHandSideExpression(expr: Expression): boolean { + export function isLeftHandSideExpression(expr: Expression): boolean { if (expr) { switch (expr.kind) { case SyntaxKind.PropertyAccessExpression: @@ -4563,7 +4563,7 @@ module ts { return false; } - function isAssignmentOperator(token: SyntaxKind): boolean { + export function isAssignmentOperator(token: SyntaxKind): boolean { return token >= SyntaxKind.FirstAssignment && token <= SyntaxKind.LastAssignment; } @@ -4634,7 +4634,7 @@ module ts { //return checkCallOrNewExpression(node); case SyntaxKind.EnumDeclaration: return checkEnumDeclaration(node); - case SyntaxKind.BinaryExpression: return checkBinaryExpression(node); + //case SyntaxKind.BinaryExpression: return checkBinaryExpression(node); case SyntaxKind.BindingElement: return checkBindingElement(node); case SyntaxKind.CatchClause: return checkCatchClause(node); case SyntaxKind.ClassDeclaration: return checkClassDeclaration(node);