From 120569afb00f7ef68fc8bd7ce1c0533978aadfbc Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 6 Jan 2016 16:12:49 -0800 Subject: [PATCH] Support for-in both with and without variable declaration --- src/compiler/checker.ts | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4cd8ef1959d..62ab2080d28 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8564,17 +8564,43 @@ namespace ts { } /** - * Return true if given node is an expression consisting of an identifier (possibly parenthesized) - * that references a variable declared in a for-in statement for an array-like object. + * Return the symbol of the for-in variable declared or referenced by the given for-in statement. */ - function isForInVariableForArrayLikeObject(node: Expression) { - const e = skipParenthesizedNodes(node); + function getForInVariableSymbol(node: ForInStatement): Symbol { + const initializer = node.initializer; + if (initializer.kind === SyntaxKind.VariableDeclarationList) { + const variable = (initializer).declarations[0]; + if (variable && !isBindingPattern(variable.name)) { + return getSymbolOfNode(variable); + } + } + else if (initializer.kind === SyntaxKind.Identifier) { + return getResolvedSymbol(initializer); + } + return undefined; + } + + /** + * Return true if given node is an expression consisting of an identifier (possibly parenthesized) + * that references a variable declared in a containing for-in statement for an array-like object. + */ + function isForInVariableForArrayLikeObject(expr: Expression) { + const e = skipParenthesizedNodes(expr); if (e.kind === SyntaxKind.Identifier) { const symbol = getResolvedSymbol(e); if (symbol.flags & SymbolFlags.Variable) { - const parent = symbol.valueDeclaration.parent.parent; - return parent.kind === SyntaxKind.ForInStatement && - isArrayLikeType(checkExpression((parent).expression)); + let child: Node = expr; + let node = expr.parent; + while (node) { + if (node.kind === SyntaxKind.ForInStatement && + child === (node).statement && + getForInVariableSymbol(node) === symbol && + isArrayLikeType(checkExpression((node).expression))) { + return true; + } + child = node; + node = node.parent; + } } } return false;