@@ -3444,6 +3444,10 @@ module ts {
34443444 }
34453445
34463446 function emitForInOrForOfStatement ( node : ForInStatement | ForOfStatement ) {
3447+ if ( languageVersion < ScriptTarget . ES6 && node . kind === SyntaxKind . ForOfStatement ) {
3448+ return emitDownLevelForOfStatement ( node ) ;
3449+ }
3450+
34473451 var endPos = emitToken ( SyntaxKind . ForKeyword , node . pos ) ;
34483452 write ( " " ) ;
34493453 endPos = emitToken ( SyntaxKind . OpenParenToken , endPos ) ;
@@ -3470,6 +3474,97 @@ module ts {
34703474 emitToken ( SyntaxKind . CloseParenToken , node . expression . end ) ;
34713475 emitEmbeddedStatement ( node . statement ) ;
34723476 }
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+ }
34733568
34743569 function emitBreakOrContinueStatement ( node : BreakOrContinueStatement ) {
34753570 emitToken ( node . kind === SyntaxKind . BreakStatement ? SyntaxKind . BreakKeyword : SyntaxKind . ContinueKeyword , node . pos ) ;
0 commit comments