@@ -745,7 +745,10 @@ module ts {
745745 forEach(symbol.declarations, node => {
746746 if (node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.ModuleDeclaration) {
747747 forEach((<ExportContainer>node).exportStars, exportStar => {
748- visit(resolveExternalModuleName(exportStar, exportStar.moduleSpecifier));
748+ var moduleSymbol = resolveExternalModuleName(exportStar, exportStar.moduleSpecifier);
749+ if (moduleSymbol) {
750+ visit(moduleSymbol);
751+ }
749752 });
750753 }
751754 });
@@ -5075,10 +5078,63 @@ module ts {
50755078
50765079 checkCollisionWithCapturedSuperVariable(node, node);
50775080 checkCollisionWithCapturedThisVariable(node, node);
5081+ checkBlockScopedBindingCapturedInLoop(node, symbol);
50785082
50795083 return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node);
50805084 }
50815085
5086+ function isInsideFunction(node: Node, threshold: Node): boolean {
5087+ var current = node;
5088+ while (current && current !== threshold) {
5089+ if (isAnyFunction(current)) {
5090+ return true;
5091+ }
5092+ current = current.parent;
5093+ }
5094+
5095+ return false;
5096+ }
5097+
5098+ function checkBlockScopedBindingCapturedInLoop(node: Identifier, symbol: Symbol): void {
5099+ if (languageVersion >= ScriptTarget.ES6 ||
5100+ (symbol.flags & SymbolFlags.BlockScopedVariable) === 0 ||
5101+ symbol.valueDeclaration.parent.kind === SyntaxKind.CatchClause) {
5102+ return;
5103+ }
5104+
5105+ // - check if binding is used in some function
5106+ // (stop the walk when reaching container of binding declaration)
5107+ // - if first check succeeded - check if variable is declared inside the loop
5108+
5109+ // nesting structure:
5110+ // (variable declaration or binding element) -> variable declaration list -> container
5111+ var container: Node = symbol.valueDeclaration;
5112+ while (container.kind !== SyntaxKind.VariableDeclarationList) {
5113+ container = container.parent;
5114+ }
5115+ // get the parent of variable declaration list
5116+ container = container.parent;
5117+ if (container.kind === SyntaxKind.VariableStatement) {
5118+ // if parent is variable statement - get its parent
5119+ container = container.parent;
5120+ }
5121+
5122+ var inFunction = isInsideFunction(node.parent, container);
5123+
5124+ var current = container;
5125+ while (current && !nodeStartsNewLexicalEnvironment(current)) {
5126+ if (isIterationStatement(current, /*lookInLabeledStatements*/ false)) {
5127+ if (inFunction) {
5128+ grammarErrorOnFirstToken(current, Diagnostics.Loop_contains_block_scoped_variable_0_referenced_by_a_function_in_the_loop_This_is_only_supported_in_ECMAScript_6_or_higher, declarationNameToString(node));
5129+ }
5130+ // mark value declaration so during emit they can have a special handling
5131+ getNodeLinks(<VariableDeclaration>symbol.valueDeclaration).flags |= NodeCheckFlags.BlockScopedBindingInLoop;
5132+ break;
5133+ }
5134+ current = current.parent;
5135+ }
5136+ }
5137+
50825138 function captureLexicalThis(node: Node, container: Node): void {
50835139 var classNode = container.parent && container.parent.kind === SyntaxKind.ClassDeclaration ? container.parent : undefined;
50845140 getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis;
@@ -10467,25 +10523,8 @@ module ts {
1046710523 }
1046810524
1046910525 function makeUniqueName(baseName: string): string {
10470- // First try '_name'
10471- if (baseName.charCodeAt(0) !== CharacterCodes._) {
10472- var baseName = "_" + baseName;
10473- if (!isExistingName(baseName)) {
10474- return generatedNames[baseName] = baseName;
10475- }
10476- }
10477- // Find the first unique '_name_n', where n is a positive number
10478- if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) {
10479- baseName += "_";
10480- }
10481- var i = 1;
10482- while (true) {
10483- name = baseName + i;
10484- if (!isExistingName(name)) {
10485- return generatedNames[name] = name;
10486- }
10487- i++;
10488- }
10526+ var name = generateUniqueName(baseName, isExistingName);
10527+ return generatedNames[name] = name;
1048910528 }
1049010529
1049110530 function assignGeneratedName(node: Node, name: string) {
@@ -10686,6 +10725,46 @@ module ts {
1068610725 !hasProperty(getGeneratedNamesForSourceFile(getSourceFile(location)), name);
1068710726 }
1068810727
10728+ function getBlockScopedVariableId(n: Identifier): number {
10729+ Debug.assert(!nodeIsSynthesized(n));
10730+
10731+ // ignore name parts of property access expressions
10732+ if (n.parent.kind === SyntaxKind.PropertyAccessExpression &&
10733+ (<PropertyAccessExpression>n.parent).name === n) {
10734+ return undefined;
10735+ }
10736+
10737+ // ignore property names in object binding patterns
10738+ if (n.parent.kind === SyntaxKind.BindingElement &&
10739+ (<BindingElement>n.parent).propertyName === n) {
10740+ return undefined;
10741+ }
10742+
10743+ // for names in variable declarations and binding elements try to short circuit and fetch symbol from the node
10744+ var declarationSymbol: Symbol =
10745+ (n.parent.kind === SyntaxKind.VariableDeclaration && (<VariableDeclaration>n.parent).name === n) ||
10746+ n.parent.kind === SyntaxKind.BindingElement
10747+ ? getSymbolOfNode(n.parent)
10748+ : undefined;
10749+
10750+ var symbol = declarationSymbol ||
10751+ getNodeLinks(n).resolvedSymbol ||
10752+ resolveName(n, n.text, SymbolFlags.BlockScopedVariable | SymbolFlags.Import, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined);
10753+
10754+ var isLetOrConst =
10755+ symbol &&
10756+ (symbol.flags & SymbolFlags.BlockScopedVariable) &&
10757+ symbol.valueDeclaration.parent.kind !== SyntaxKind.CatchClause;
10758+
10759+ if (isLetOrConst) {
10760+ // side-effect of calling this method:
10761+ // assign id to symbol if it was not yet set
10762+ getSymbolLinks(symbol);
10763+ return symbol.id;
10764+ }
10765+ return undefined;
10766+ }
10767+
1068910768 function createResolver(): EmitResolver {
1069010769 return {
1069110770 getGeneratedNameForNode,
@@ -10702,6 +10781,7 @@ module ts {
1070210781 isEntityNameVisible,
1070310782 getConstantValue,
1070410783 isUnknownIdentifier,
10784+ getBlockScopedVariableId,
1070510785 };
1070610786 }
1070710787
@@ -11443,7 +11523,8 @@ module ts {
1144311523 if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) {
1144411524 return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer);
1144511525 }
11446- if (isConst(node)) {
11526+ // const declarations should not be initialized in for-in for-of statements
11527+ if (isConst(node) && node.parent.parent.kind !== SyntaxKind.ForInStatement && node.parent.parent.kind !== SyntaxKind.ForOfStatement) {
1144711528 return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized);
1144811529 }
1144911530 }
@@ -11485,15 +11566,6 @@ module ts {
1148511566 if (!declarationList.declarations.length) {
1148611567 return grammarErrorAtPos(getSourceFileOfNode(declarationList), declarations.pos, declarations.end - declarations.pos, Diagnostics.Variable_declaration_list_cannot_be_empty);
1148711568 }
11488-
11489- if (languageVersion < ScriptTarget.ES6) {
11490- if (isLet(declarationList)) {
11491- return grammarErrorOnFirstToken(declarationList, Diagnostics.let_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
11492- }
11493- else if (isConst(declarationList)) {
11494- return grammarErrorOnFirstToken(declarationList, Diagnostics.const_declarations_are_only_available_when_targeting_ECMAScript_6_and_higher);
11495- }
11496- }
1149711569 }
1149811570
1149911571 function allowLetAndConstDeclarations(parent: Node): boolean {
0 commit comments