src/codegeneration/BlockBindingTransformer.js
function varNeedsInitializer(tree, loopTree) {
  if (loopTree === null) return false;

  // Loop initializers for for-in/for-of must not have an initializer RHS.
  let type = loopTree.type;
  if (type !== FOR_IN_STATEMENT && type !== FOR_OF_STATEMENT) return true;
  return loopTree.initializer.declarations[0] !== tree;
}
function varNeedsInitializer(tree, loopTree) {
  if (loopTree === null) return false;

  // Loop initializers for for-in/for-of must not have an initializer RHS.
  let type = loopTree.type;
  if (type !== FOR_IN_STATEMENT && type !== FOR_OF_STATEMENT) return true;
  return loopTree.initializer.declarations[0] !== tree;
}
function varNeedsInitializer ( tree , loopTree ) { if ( loopTree === null ) return false ; // Loop initializers for for-in/for-of must not have an initializer RHS. let type = loopTree . type ; if ( type !== FOR_IN_STATEMENT && type !== FOR_OF_STATEMENT ) return true ; return loopTree . initializer . declarations [ 0 ] !== tree ; }
Transforms the block bindings from traceur to js.

In most cases, let can be transformed to var straight away and renamed to
avoid name collisions.

Making a

if (true) { let t = 5; }

Become a

if (true) { var t$__0 = 5; }

The only special case is in Iterable statements. For those, we only use a
different strategy if they use let in them and they define functions that use
those block binded variables. In that case, the loop content is extracted to
a function, that gets called on every iteration with its arguments being
any variable declared in the loop initializer.
If the loop contained any break/continue statements, they get extracted and
transformed to return statements of numbers, that correspond to the correct
statement in a switch case.

Example:

for (let i = 0; i < 5; i++) {
if (i === 3) break;
setTimeout(function () {
log(i);
});
}

Becomes:

// the loop content extracted to a function
var $__2 = function (i) {
if (i === 3) return 0;
setTimeout(function () {
log(i);
});
}, $__3;

// the loop gets labelled if needed (it is here)
$__1:
for (var i$__0 = 0; i$__0 < 5; i$__0++) {
$__3 = $__2(i$__0);
switch($__3) {
case 0:
break $__1; // breaks the loop
}
}

If the loop contained return statements, they get transformed to returning
object which preserver the scope in which the expression get executed.

Example:

for (let i = 0; i < 5; i++) {
if (i === 3) return i + 10;
// without this the let would just become a var
setTimeout(function () { log(i) });
}

Becomes:

var $__1 = function(i) {
if (i === 3) return {v: i + 10};
setTimeout(function() { log(i); });
}, $__2;
for (var i$__0 = 0; i$__0 < 5; i$__0++) {
$__2 = $__1(i$__0);
if (typeof $__2 === "object")
return $__2.v;
}


If a loop contained both break/continue and return statements, the if-typeof
statement from the second example would be added as a default clause to the
switch statement of the first example.


const variables are handled the same way.

The block binding rewrite pass assumes that deconstructing assignments
and variable declarations have already been desugared. See getVariableName_.

Note:

If the transformation happens inside a generator, the inner function
becomes an inner generator.
Transforms the block bindings from traceur to js .