@@ -1641,14 +1641,13 @@ module ts {
1641
1641
}
1642
1642
1643
1643
if ( root ) {
1644
- currentSourceFile = root ;
1645
- emit ( root ) ;
1644
+ // Do not call emit directly. It does not set the currentSourceFile.
1645
+ emitSourceFile ( root ) ;
1646
1646
}
1647
1647
else {
1648
1648
forEach ( host . getSourceFiles ( ) , sourceFile => {
1649
- currentSourceFile = sourceFile ;
1650
1649
if ( ! isExternalModuleOrDeclarationFile ( sourceFile ) ) {
1651
- emit ( sourceFile ) ;
1650
+ emitSourceFile ( sourceFile ) ;
1652
1651
}
1653
1652
} ) ;
1654
1653
}
@@ -1657,6 +1656,11 @@ module ts {
1657
1656
writeEmittedFiles ( writer . getText ( ) , /*writeByteOrderMark*/ compilerOptions . emitBOM ) ;
1658
1657
return ;
1659
1658
1659
+ function emitSourceFile ( sourceFile : SourceFile ) : void {
1660
+ currentSourceFile = sourceFile ;
1661
+ emit ( sourceFile ) ;
1662
+ }
1663
+
1660
1664
// enters the new lexical environment
1661
1665
// return value should be passed to matching call to exitNameScope.
1662
1666
function enterNameScope ( ) : boolean {
@@ -1689,10 +1693,10 @@ module ts {
1689
1693
name = generateUniqueName ( baseName , n => isExistingName ( location , n ) ) ;
1690
1694
}
1691
1695
1692
- return putNameInCurrentScopeNames ( name ) ;
1696
+ return recordNameInCurrentScope ( name ) ;
1693
1697
}
1694
1698
1695
- function putNameInCurrentScopeNames ( name : string ) : string {
1699
+ function recordNameInCurrentScope ( name : string ) : string {
1696
1700
if ( ! currentScopeNames ) {
1697
1701
currentScopeNames = { } ;
1698
1702
}
@@ -1702,7 +1706,7 @@ module ts {
1702
1706
1703
1707
function isExistingName ( location : Node , name : string ) {
1704
1708
// check if resolver is aware of this name (if name was seen during the typecheck)
1705
- if ( ! resolver . isUnknownIdentifier ( location , name , currentSourceFile ) ) {
1709
+ if ( ! resolver . isUnknownIdentifier ( location , name ) ) {
1706
1710
return true ;
1707
1711
}
1708
1712
@@ -2107,13 +2111,14 @@ module ts {
2107
2111
break ;
2108
2112
}
2109
2113
// _a .. _h, _j ... _z, _0, _1, ...
2114
+ // Note that _i is skipped
2110
2115
name = "_" + ( tempCount < 25 ? String . fromCharCode ( tempCount + ( tempCount < 8 ? 0 : 1 ) + CharacterCodes . a ) : tempCount - 25 ) ;
2111
2116
tempCount ++ ;
2112
2117
}
2113
2118
2114
2119
// This is necessary so that a name generated via renameNonTopLevelLetAndConst will see the name
2115
2120
// we just generated.
2116
- putNameInCurrentScopeNames ( name ) ;
2121
+ recordNameInCurrentScope ( name ) ;
2117
2122
2118
2123
var result = < Identifier > createSynthesizedNode ( SyntaxKind . Identifier ) ;
2119
2124
result . text = name ;
@@ -3315,7 +3320,7 @@ module ts {
3315
3320
function emitBinaryExpression ( node : BinaryExpression ) {
3316
3321
if ( languageVersion < ScriptTarget . ES6 && node . operatorToken . kind === SyntaxKind . EqualsToken &&
3317
3322
( node . left . kind === SyntaxKind . ObjectLiteralExpression || node . left . kind === SyntaxKind . ArrayLiteralExpression ) ) {
3318
- emitDestructuring ( node ) ;
3323
+ emitDestructuring ( node , node . parent . kind === SyntaxKind . ExpressionStatement ) ;
3319
3324
}
3320
3325
else {
3321
3326
emit ( node . left ) ;
@@ -3595,7 +3600,7 @@ module ts {
3595
3600
3596
3601
// Do not emit the LHS var declaration yet, because it might contain destructuring.
3597
3602
3598
- // Do not call create recordTempDeclaration because we are declaring the temps
3603
+ // Do not call recordTempDeclaration because we are declaring the temps
3599
3604
// right here. Recording means they will be declared later.
3600
3605
// In the case where the user wrote an identifier as the RHS, like this:
3601
3606
//
@@ -3655,12 +3660,12 @@ module ts {
3655
3660
if ( node . initializer . kind === SyntaxKind . VariableDeclarationList ) {
3656
3661
write ( "var " ) ;
3657
3662
var variableDeclarationList = < VariableDeclarationList > node . initializer ;
3658
- if ( variableDeclarationList . declarations . length >= 1 ) {
3663
+ if ( variableDeclarationList . declarations . length > 0 ) {
3659
3664
var declaration = variableDeclarationList . declarations [ 0 ] ;
3660
3665
if ( isBindingPattern ( declaration . name ) ) {
3661
3666
// This works whether the declaration is a var, let, or const.
3662
3667
// It will use rhsIterationValue _a[_i] as the initializer.
3663
- emitDestructuring ( declaration , rhsIterationValue ) ;
3668
+ emitDestructuring ( declaration , /*isAssignmentExpressionStatement*/ false , rhsIterationValue ) ;
3664
3669
}
3665
3670
else {
3666
3671
// The following call does not include the initializer, so we have
@@ -3673,8 +3678,7 @@ module ts {
3673
3678
else {
3674
3679
// It's an empty declaration list. This can only happen in an error case, if the user wrote
3675
3680
// for (var of []) {}
3676
- var emptyDeclarationListTemp = createTempVariable ( node , /*forLoopVariable*/ false ) ;
3677
- emitNode ( emptyDeclarationListTemp ) ;
3681
+ emitNode ( createTempVariable ( node , /*forLoopVariable*/ false ) ) ;
3678
3682
write ( " = " ) ;
3679
3683
emitNode ( rhsIterationValue ) ;
3680
3684
}
@@ -3683,11 +3687,10 @@ module ts {
3683
3687
// Initializer is an expression. Emit the expression in the body, so that it's
3684
3688
// evaluated on every iteration.
3685
3689
var assignmentExpression = createBinaryExpression ( < Expression > node . initializer , SyntaxKind . EqualsToken , rhsIterationValue , /*startsOnNewLine*/ false ) ;
3686
- var assignmentExpressionStatement = createExpressionStatement ( assignmentExpression ) ;
3687
3690
if ( node . initializer . kind === SyntaxKind . ArrayLiteralExpression || node . initializer . kind === SyntaxKind . ObjectLiteralExpression ) {
3688
3691
// This is a destructuring pattern, so call emitDestructuring instead of emit. Calling emit will not work, because it will cause
3689
3692
// the BinaryExpression to be passed in instead of the expression statement, which will cause emitDestructuring to crash.
3690
- emitDestructuring ( assignmentExpressionStatement ) ;
3693
+ emitDestructuring ( assignmentExpression , /*isAssignmentExpressionStatement*/ true , /*value*/ undefined , /*locationForCheckingExistingName*/ node ) ;
3691
3694
}
3692
3695
else {
3693
3696
emitNode ( assignmentExpression ) ;
@@ -3864,16 +3867,25 @@ module ts {
3864
3867
}
3865
3868
}
3866
3869
3867
- // Note that a destructuring assignment can be either an ExpressionStatement or a BinaryExpression.
3868
- function emitDestructuring ( root : ExpressionStatement | BinaryExpression | VariableDeclaration | ParameterDeclaration , value ?: Expression ) {
3870
+ /**
3871
+ * If the root has a chance of being a synthesized node, callers should also pass a value for
3872
+ * lowestNonSynthesizedAncestor. This should be an ancestor of root, it should not be synthesized,
3873
+ * and there should not be a lower ancestor that introduces a scope. This node will be used as the
3874
+ * location for ensuring that temporary names are unique.
3875
+ */
3876
+ function emitDestructuring ( root : BinaryExpression | VariableDeclaration | ParameterDeclaration ,
3877
+ isAssignmentExpressionStatement : boolean ,
3878
+ value ?: Expression ,
3879
+ lowestNonSynthesizedAncestor ?: Node ) {
3869
3880
var emitCount = 0 ;
3870
3881
// An exported declaration is actually emitted as an assignment (to a property on the module object), so
3871
3882
// temporary variables in an exported declaration need to have real declarations elsewhere
3872
3883
var isDeclaration = ( root . kind === SyntaxKind . VariableDeclaration && ! ( getCombinedNodeFlags ( root ) & NodeFlags . Export ) ) || root . kind === SyntaxKind . Parameter ;
3873
- if ( root . kind === SyntaxKind . ExpressionStatement || root . kind === SyntaxKind . BinaryExpression ) {
3874
- emitAssignmentExpression ( < ExpressionStatement | BinaryExpression > root ) ;
3884
+ if ( root . kind === SyntaxKind . BinaryExpression ) {
3885
+ emitAssignmentExpression ( < BinaryExpression > root ) ;
3875
3886
}
3876
3887
else {
3888
+ Debug . assert ( ! isAssignmentExpressionStatement ) ;
3877
3889
emitBindingElement ( < BindingElement > root , value ) ;
3878
3890
}
3879
3891
@@ -3895,7 +3907,10 @@ module ts {
3895
3907
3896
3908
function ensureIdentifier ( expr : Expression ) : Expression {
3897
3909
if ( expr . kind !== SyntaxKind . Identifier ) {
3898
- var identifier = createTempVariable ( root ) ;
3910
+ // In case the root is a synthesized node, we need to pass lowestNonSynthesizedAncestor
3911
+ // as the location for determining uniqueness of the variable we are about to
3912
+ // generate.
3913
+ var identifier = createTempVariable ( lowestNonSynthesizedAncestor || root ) ;
3899
3914
if ( ! isDeclaration ) {
3900
3915
recordTempDeclaration ( identifier ) ;
3901
3916
}
@@ -4013,14 +4028,13 @@ module ts {
4013
4028
}
4014
4029
}
4015
4030
4016
- function emitAssignmentExpression ( root : ExpressionStatement | BinaryExpression ) {
4017
- // Synthesized nodes will not have parents, so the ExpressionStatements will have to be passed
4018
- // in directly. Otherwise, it will crash when we access the parent of a synthesized binary expression.
4019
- var emitParenthesized = root . kind !== SyntaxKind . ExpressionStatement && root . parent . kind !== SyntaxKind . ExpressionStatement ;
4020
- var expression = < BinaryExpression > ( root . kind === SyntaxKind . ExpressionStatement ? ( < ExpressionStatement > root ) . expression : < BinaryExpression > root ) ;
4021
- var target = expression . left ;
4022
- var value = expression . right ;
4023
- if ( emitParenthesized ) {
4031
+ function emitAssignmentExpression ( root : BinaryExpression ) {
4032
+ var target = root . left ;
4033
+ var value = root . right ;
4034
+ if ( isAssignmentExpressionStatement ) {
4035
+ emitDestructuringAssignment ( target , value ) ;
4036
+ }
4037
+ else {
4024
4038
if ( root . parent . kind !== SyntaxKind . ParenthesizedExpression ) {
4025
4039
write ( "(" ) ;
4026
4040
}
@@ -4032,9 +4046,6 @@ module ts {
4032
4046
write ( ")" ) ;
4033
4047
}
4034
4048
}
4035
- else {
4036
- emitDestructuringAssignment ( target , value ) ;
4037
- }
4038
4049
}
4039
4050
4040
4051
function emitBindingElement ( target : BindingElement , value : Expression ) {
@@ -4085,7 +4096,7 @@ module ts {
4085
4096
function emitVariableDeclaration ( node : VariableDeclaration ) {
4086
4097
if ( isBindingPattern ( node . name ) ) {
4087
4098
if ( languageVersion < ScriptTarget . ES6 ) {
4088
- emitDestructuring ( node ) ;
4099
+ emitDestructuring ( node , /*isAssignmentExpressionStatement*/ false ) ;
4089
4100
}
4090
4101
else {
4091
4102
emit ( node . name ) ;
@@ -4248,7 +4259,7 @@ module ts {
4248
4259
if ( isBindingPattern ( p . name ) ) {
4249
4260
writeLine ( ) ;
4250
4261
write ( "var " ) ;
4251
- emitDestructuring ( p , tempParameters [ tempIndex ] ) ;
4262
+ emitDestructuring ( p , /*isAssignmentExpressionStatement*/ false , tempParameters [ tempIndex ] ) ;
4252
4263
write ( ";" ) ;
4253
4264
tempIndex ++ ;
4254
4265
}
@@ -5310,7 +5321,7 @@ module ts {
5310
5321
return statements . length ;
5311
5322
}
5312
5323
5313
- function emitSourceFile ( node : SourceFile ) {
5324
+ function emitSourceFileNode ( node : SourceFile ) {
5314
5325
// Start new file on new line
5315
5326
writeLine ( ) ;
5316
5327
emitDetachedComments ( node ) ;
@@ -5553,7 +5564,7 @@ module ts {
5553
5564
case SyntaxKind . ExportDeclaration :
5554
5565
return emitExportDeclaration ( < ExportDeclaration > node ) ;
5555
5566
case SyntaxKind . SourceFile :
5556
- return emitSourceFile ( < SourceFile > node ) ;
5567
+ return emitSourceFileNode ( < SourceFile > node ) ;
5557
5568
}
5558
5569
}
5559
5570
0 commit comments