Repository: Rich-Harris/buble (js)

Issue:
Destructuring assignments in for-of loop heads are not transpiled
Example:

```js
var x; for ({x} of []) {a();}
```

Destructuring variable declarations work, though.

Pull request description:
Support destructuring assignments in for-of loop
Fixes #71.

Patch:
diff --git a/src/program/types/ForOfStatement.js b/src/program/types/ForOfStatement.js
index 6309a57..2bf0e61 100644
--- a/src/program/types/ForOfStatement.js
+++ b/src/program/types/ForOfStatement.js
@@ -52,19 +52,18 @@ export default class ForOfStatement extends LoopStatement {
 		code.prependRight(this.right.start, `var ${key} = 0, ${list} = `);
 		code.appendLeft(this.right.end, `; ${key} < ${list}.length; ${key} += 1`);
 
-		// destructuring. TODO non declaration destructuring
-		const declarator =
-			this.left.type === 'VariableDeclaration' && this.left.declarations[0];
-		if (declarator && declarator.id.type !== 'Identifier') {
+		const isDeclaration = this.left.type === 'VariableDeclaration';
+		const maybeDestructuring = isDeclaration ? this.left.declarations[0].id : this.left;
+		if (maybeDestructuring.type !== 'Identifier') {
 			let statementGenerators = [];
 			const ref = scope.createIdentifier('ref');
 			destructure(
 				code,
 				id => scope.createIdentifier(id),
 				({ name }) => scope.resolveName(name),
-				declarator.id,
+				maybeDestructuring,
 				ref,
-				false,
+				!isDeclaration,
 				statementGenerators
 			);
 
@@ -77,8 +76,12 @@ export default class ForOfStatement extends LoopStatement {
 				fn(bodyStart, '', suffix);
 			});
 
-			code.appendLeft(this.left.start + this.left.kind.length + 1, ref);
-			code.appendLeft(this.left.end, ` = ${list}[${key}];\n${i1}`);
+			if (isDeclaration) {
+				code.appendLeft(this.left.start + this.left.kind.length + 1, ref);
+				code.appendLeft(this.left.end, ` = ${list}[${key}];\n${i1}`);
+			} else {
+				code.appendLeft(this.left.end, `var ${ref} = ${list}[${key}];\n${i1}`);
+			}
 		} else {
 			code.appendLeft(this.left.end, ` = ${list}[${key}];\n\n${i1}`);
 		}


Test patch:
diff --git a/test/samples/for-of.js b/test/samples/for-of.js
index ec9b643..2f32cd2 100644
--- a/test/samples/for-of.js
+++ b/test/samples/for-of.js
@@ -223,5 +223,51 @@ module.exports = [
 
 				console.log(x, y);
 			}`
+	},
+
+	{
+		description: 'destructures assignment in forOf loop',
+		options: { transforms: { dangerousForOf: true } },
+
+		input: `
+			var x, y;
+			for ({x, y} of [{x: 1, y: 2}]) {
+				console.log(x, y);
+			}
+		`,
+
+		output: `
+			var x, y;
+			for (var i = 0, list = [{x: 1, y: 2}]; i < list.length; i += 1) {
+				var ref = list[i];
+				x = ref.x;
+				y = ref.y;
+
+				console.log(x, y);
+			}
+		`
+	},
+
+	{
+		description: 'destructures assignment in forOf loop with array pattern',
+		options: { transforms: { dangerousForOf: true } },
+
+		input: `
+			var x, y;
+			for ([x, y] of [[1, 2]]) {
+				console.log(x, y);
+			}
+		`,
+
+		output: `
+			var x, y;
+			for (var i = 0, list = [[1, 2]]; i < list.length; i += 1) {
+				var ref = list[i];
+				x = ref[0];
+				y = ref[1];
+
+				console.log(x, y);
+			}
+		`
 	}
 ];