@@ -3444,6 +3444,10 @@ module ts {
3444
3444
}
3445
3445
3446
3446
function emitForInOrForOfStatement ( node : ForInStatement | ForOfStatement ) {
3447
+ if ( languageVersion < ScriptTarget . ES6 && node . kind === SyntaxKind . ForOfStatement ) {
3448
+ return emitDownLevelForOfStatement ( node ) ;
3449
+ }
3450
+
3447
3451
var endPos = emitToken ( SyntaxKind . ForKeyword , node . pos ) ;
3448
3452
write ( " " ) ;
3449
3453
endPos = emitToken ( SyntaxKind . OpenParenToken , endPos ) ;
@@ -3470,6 +3474,97 @@ module ts {
3470
3474
emitToken ( SyntaxKind . CloseParenToken , node . expression . end ) ;
3471
3475
emitEmbeddedStatement ( node . statement ) ;
3472
3476
}
3477
+
3478
+ function emitDownLevelForOfStatement ( node : ForOfStatement ) {
3479
+ // The following ES6 code:
3480
+ //
3481
+ // for (var v of expr) { }
3482
+ //
3483
+ // should be emitted as
3484
+ //
3485
+ // for (var v, _i = 0, _a = expr; _i < _a.length; _i++) {
3486
+ // v = _a[_i];
3487
+ // }
3488
+ //
3489
+ // where _a and _i are temps emitted to capture the RHS and the counter,
3490
+ // respectively.
3491
+ // When the left hand side is an expression instead of a var declaration,
3492
+ // the "var v" is not emitted.
3493
+ // When the left hand side is a let/const, the v is renamed if there is
3494
+ // another v in scope.
3495
+ // Note that all assignments to the LHS are emitted in the body, including
3496
+ // all destructuring.
3497
+ // Note also that because an extra statement is needed to assign to the LHS,
3498
+ // for-of bodies are always emitted as blocks.
3499
+
3500
+ var endPos = emitToken ( SyntaxKind . ForKeyword , node . pos ) ;
3501
+ write ( " " ) ;
3502
+ endPos = emitToken ( SyntaxKind . OpenParenToken , endPos ) ;
3503
+ if ( node . initializer . kind === SyntaxKind . VariableDeclarationList ) {
3504
+ var variableDeclarationList = < VariableDeclarationList > node . initializer ;
3505
+ if ( variableDeclarationList . declarations . length >= 1 ) {
3506
+ write ( "var " ) ;
3507
+ var decl = variableDeclarationList . declarations [ 0 ] ;
3508
+ // TODO handle binding patterns
3509
+ emit ( decl . name ) ;
3510
+ write ( ", " ) ;
3511
+ }
3512
+ }
3513
+
3514
+ // Do not call create recordTempDeclaration because we are declaring the temps
3515
+ // right here. Recording means they will be declared later.
3516
+ var counter = createTempVariable ( node , /*forLoopVariable*/ true ) ;
3517
+ var rhsReference = createTempVariable ( node , /*forLoopVariable*/ false ) ;
3518
+
3519
+ // _i = 0,
3520
+ emit ( counter ) ;
3521
+ write ( " = 0, " ) ;
3522
+
3523
+ // _a = expr;
3524
+ emit ( rhsReference ) ;
3525
+ write ( " = " ) ;
3526
+ emit ( node . expression ) ;
3527
+ write ( "; " ) ;
3528
+
3529
+ // _i < _a.length;
3530
+ emit ( counter ) ;
3531
+ write ( " < " ) ;
3532
+ emit ( rhsReference ) ;
3533
+ write ( ".length; " ) ;
3534
+
3535
+ // _i++)
3536
+ emit ( counter ) ;
3537
+ write ( "++" ) ;
3538
+ emitToken ( SyntaxKind . CloseParenToken , node . expression . end ) ;
3539
+
3540
+ // Body
3541
+ write ( " {" ) ;
3542
+ writeLine ( ) ;
3543
+ increaseIndent ( ) ;
3544
+
3545
+ // Initialize LHS
3546
+ // v = _a[_i];
3547
+ if ( decl ) {
3548
+ emit ( decl . name ) ;
3549
+ write ( " = " ) ;
3550
+ emit ( rhsReference )
3551
+ write ( "[" ) ;
3552
+ emit ( counter ) ;
3553
+ write ( "];" ) ;
3554
+ writeLine ( ) ;
3555
+ }
3556
+
3557
+ if ( node . statement . kind === SyntaxKind . Block ) {
3558
+ emitLines ( ( < Block > node . statement ) . statements ) ;
3559
+ }
3560
+ else {
3561
+ emit ( node . statement ) ;
3562
+ }
3563
+
3564
+ writeLine ( ) ;
3565
+ decreaseIndent ( ) ;
3566
+ write ( "}" ) ;
3567
+ }
3473
3568
3474
3569
function emitBreakOrContinueStatement ( node : BreakOrContinueStatement ) {
3475
3570
emitToken ( node . kind === SyntaxKind . BreakStatement ? SyntaxKind . BreakKeyword : SyntaxKind . ContinueKeyword , node . pos ) ;
0 commit comments