@@ -745,7 +745,10 @@ module ts {
745
745
forEach(symbol.declarations, node => {
746
746
if (node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.ModuleDeclaration) {
747
747
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
+ }
749
752
});
750
753
}
751
754
});
@@ -5075,10 +5078,63 @@ module ts {
5075
5078
5076
5079
checkCollisionWithCapturedSuperVariable(node, node);
5077
5080
checkCollisionWithCapturedThisVariable(node, node);
5081
+ checkBlockScopedBindingCapturedInLoop(node, symbol);
5078
5082
5079
5083
return getNarrowedTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol), node);
5080
5084
}
5081
5085
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
+
5082
5138
function captureLexicalThis(node: Node, container: Node): void {
5083
5139
var classNode = container.parent && container.parent.kind === SyntaxKind.ClassDeclaration ? container.parent : undefined;
5084
5140
getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis;
@@ -10467,25 +10523,8 @@ module ts {
10467
10523
}
10468
10524
10469
10525
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;
10489
10528
}
10490
10529
10491
10530
function assignGeneratedName(node: Node, name: string) {
@@ -10686,6 +10725,46 @@ module ts {
10686
10725
!hasProperty(getGeneratedNamesForSourceFile(getSourceFile(location)), name);
10687
10726
}
10688
10727
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
+
10689
10768
function createResolver(): EmitResolver {
10690
10769
return {
10691
10770
getGeneratedNameForNode,
@@ -10702,6 +10781,7 @@ module ts {
10702
10781
isEntityNameVisible,
10703
10782
getConstantValue,
10704
10783
isUnknownIdentifier,
10784
+ getBlockScopedVariableId,
10705
10785
};
10706
10786
}
10707
10787
@@ -11443,7 +11523,8 @@ module ts {
11443
11523
if (isBindingPattern(node.name) && !isBindingPattern(node.parent)) {
11444
11524
return grammarErrorOnNode(node, Diagnostics.A_destructuring_declaration_must_have_an_initializer);
11445
11525
}
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) {
11447
11528
return grammarErrorOnNode(node, Diagnostics.const_declarations_must_be_initialized);
11448
11529
}
11449
11530
}
@@ -11485,15 +11566,6 @@ module ts {
11485
11566
if (!declarationList.declarations.length) {
11486
11567
return grammarErrorAtPos(getSourceFileOfNode(declarationList), declarations.pos, declarations.end - declarations.pos, Diagnostics.Variable_declaration_list_cannot_be_empty);
11487
11568
}
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
- }
11497
11569
}
11498
11570
11499
11571
function allowLetAndConstDeclarations(parent: Node): boolean {
0 commit comments