diff --git a/src/program/types/ForOfStatement.js b/src/program/types/ForOfStatement.js index afe479c0..387ba4ee 100644 --- a/src/program/types/ForOfStatement.js +++ b/src/program/types/ForOfStatement.js @@ -33,10 +33,11 @@ export default class ForOfStatement extends LoopStatement { const key = scope.createIdentifier( 'i' ); const list = scope.createIdentifier( 'list' ); + const useLen = scope.createIdentifier( 'useLen' ); if ( this.body.synthetic ) { code.insertRight( this.left.start, `{\n${i1}` ); - code.insertLeft( this.body.body[0].end, `\n${i0}}` ); + code.insertLeft( this.body.end, `\n${i0}}` ); } const bodyStart = this.body.body[0].start; @@ -46,7 +47,9 @@ export default class ForOfStatement extends LoopStatement { code.insertRight( this.right.start, `var ${key} = 0, ${list} = ` ); - code.insertLeft( this.right.end, `; ${key} < ${list}.length; ${key} += 1` ); + code.insertLeft( this.right.end, `, ${useLen} = typeof ${list}.length === 'number' || typeof Symbol !== 'function', ${list} = ${useLen} ? ${list} : ${list}[Symbol.iterator](); ${useLen} ? ${key} < ${list}.length : !(${key} = ${list}.next()).done;` ); + + const getVal = `${useLen} ? ${list}[${key}++] : ${key}.value`; // destructuring. TODO non declaration destructuring const declarator = this.left.type === 'VariableDeclaration' && this.left.declarations[0]; @@ -65,9 +68,9 @@ export default class ForOfStatement extends LoopStatement { }); code.insertLeft( this.left.start + this.left.kind.length + 1, ref ); - code.insertLeft( this.left.end, ` = ${list}[${key}];\n${i1}` ); + code.insertLeft( this.left.end, ` = ${getVal};\n${i1}` ); } else { - code.insertLeft( this.left.end, ` = ${list}[${key}];\n\n${i1}` ); + code.insertLeft( this.left.end, ` = ${getVal};\n\n${i1}` ); } super.transpile( code, transforms ); diff --git a/test/samples/for-of.js b/test/samples/for-of.js index 01363914..ae7bd5a4 100644 --- a/test/samples/for-of.js +++ b/test/samples/for-of.js @@ -22,8 +22,8 @@ module.exports = [ }`, output: ` - for ( var i = 0, list = array; i < list.length; i += 1 ) { - var member = list[i]; + for ( var i = 0, list = array, useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done; ) { + var member = useLen ? list[i++] : i.value; doSomething( member ); }` @@ -39,8 +39,8 @@ module.exports = [ }`, output: ` - for ( var i = 0, list = [ 'a', 'b', 'c' ]; i < list.length; i += 1 ) { - var member = list[i]; + for ( var i = 0, list = [ 'a', 'b', 'c' ], useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done; ) { + var member = useLen ? list[i++] : i.value; doSomething( member ); }` @@ -59,14 +59,14 @@ module.exports = [ output: ` var loop = function () { - var member = list[i]; + var member = useLen ? list[i++] : i.value; setTimeout( function () { doSomething( member ); }); }; - for ( var i = 0, list = [ 'a', 'b', 'c' ]; i < list.length; i += 1 ) loop();` + for ( var i = 0, list = [ 'a', 'b', 'c' ], useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done; ) loop();` }, { @@ -77,8 +77,8 @@ module.exports = [ for ( let member of array ) console.log( member );`, output: ` - for ( var i = 0, list = array; i < list.length; i += 1 ) { - var member = list[i]; + for ( var i = 0, list = array, useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done; ) { + var member = useLen ? list[i++] : i.value; console.log( member ); }` @@ -94,8 +94,8 @@ module.exports = [ }`, output: ` - for (var i = 0, list = this.keys; i < list.length; i += 1) { - var key = list[i]; + for (var i = 0, list = this.keys, useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done;) { + var key = useLen ? list[i++] : i.value; console.log(key); }` @@ -111,8 +111,8 @@ module.exports = [ }`, output: ` - for ( var i = 0, list = items; i < list.length; i += 1 ) { - var item = list[i]; + for ( var i = 0, list = items, useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done; ) { + var item = useLen ? list[i++] : i.value; if ( item.foo ) { continue; } }` @@ -136,7 +136,7 @@ module.exports = [ var this$1 = this; var loop = function () { - var item = list[i]; + var item = useLen ? list[i++] : i.value; console.log( this$1, arguments$1, item ); setTimeout( function () { @@ -144,7 +144,7 @@ module.exports = [ }); }; - for ( var i = 0, list = items; i < list.length; i += 1 ) loop();` + for ( var i = 0, list = items, useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done; ) loop();` }, { @@ -187,7 +187,7 @@ module.exports = [ output: ` function foo () { var loop = function () { - var x = list[i]; + var x = useLen ? list[i++] : i.value; setTimeout( function () { console.log( x ); @@ -196,7 +196,7 @@ module.exports = [ if ( x > 10 ) { return {}; } }; - for ( var i = 0, list = y; i < list.length; i += 1 ) { + for ( var i = 0, list = y, useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done; ) { var returned = loop(); if ( returned ) return returned.v; @@ -214,8 +214,8 @@ module.exports = [ }`, output: ` - for (var i = 0, list = [{x: 1, y: 2}]; i < list.length; i += 1) { - var ref = list[i]; + for (var i = 0, list = [{x: 1, y: 2}], useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done;) { + var ref = useLen ? list[i++] : i.value; var x = ref.x; var y = ref.y; diff --git a/test/samples/loops.js b/test/samples/loops.js index 10c4857c..4ef0cf54 100644 --- a/test/samples/loops.js +++ b/test/samples/loops.js @@ -504,8 +504,8 @@ module.exports = [ output: ` for (var a = 0; a < 10; a++) { var j = 1, k = (void 0); - for (var i = 0, list = c; i < list.length; i += 1) { - var b = list[i]; + for (var i = 0, list = c, useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done;) { + var b = useLen ? list[i++] : i.value; var x = (void 0), y = 2 f(b, j, k, x, y) @@ -526,8 +526,8 @@ module.exports = [ } `, output: ` - for (var i = 0, list = c; i < list.length; i += 1) { - var b = list[i]; + for (var i = 0, list = c, useLen = typeof list.length === 'number' || typeof Symbol !== 'function', list = useLen ? list : list[Symbol.iterator](); useLen ? i < list.length : !(i = list.next()).done;) { + var b = useLen ? list[i++] : i.value; var x = (void 0), y = 2, z = (void 0); f(b, x++, y++, z++)