From bd44d30a007afdaabb9ddbe56e9a4c5cc036f7c1 Mon Sep 17 00:00:00 2001
From: Mike Pennisi <mike@mikepennisi.com>
Date: Wed, 18 Feb 2015 17:56:07 -0500
Subject: [PATCH] Import tests from Google V8 (iteration semantics)

These tests are derived from the following files within the Google V8
project:

test/mjsunit/es6/iteration-semantics.js
---
 test/language/for-of/break-from-catch.js      |  29 ++++
 test/language/for-of/break-from-try.js        |  28 ++++
 test/language/for-of/break-label.js           |  28 ++++
 test/language/for-of/break.js                 |  23 ++++
 test/language/for-of/continue-from-catch.js   |  28 ++++
 test/language/for-of/continue-from-try.js     |  27 ++++
 test/language/for-of/continue-label.js        |  30 ++++
 test/language/for-of/continue.js              |  23 ++++
 test/language/for-of/generator.js             |  23 ++++
 test/language/for-of/generic-iterable.js      |  27 ++++
 .../for-of/head-expr-obj-iterator-method.js   |  13 ++
 .../head-expr-primitive-iterator-method.js    |  17 +++
 test/language/for-of/head-expr-to-obj.js      |  17 +++
 test/language/for-of/iterator-as-proxy.js     |  35 +++++
 .../for-of/iterator-next-reference.js         |  40 ++++++
 .../for-of/iterator-next-result-done-attr.js  | 129 ++++++++++++++++++
 .../for-of/iterator-next-result-type.js       | 105 ++++++++++++++
 .../for-of/iterator-next-result-value-attr.js |  47 +++++++
 test/language/for-of/nested.js                |  37 +++++
 test/language/for-of/return.js                |  28 ++++
 20 files changed, 734 insertions(+)
 create mode 100644 test/language/for-of/break-from-catch.js
 create mode 100644 test/language/for-of/break-from-try.js
 create mode 100644 test/language/for-of/break-label.js
 create mode 100644 test/language/for-of/break.js
 create mode 100644 test/language/for-of/continue-from-catch.js
 create mode 100644 test/language/for-of/continue-from-try.js
 create mode 100644 test/language/for-of/continue-label.js
 create mode 100644 test/language/for-of/continue.js
 create mode 100644 test/language/for-of/generator.js
 create mode 100644 test/language/for-of/generic-iterable.js
 create mode 100644 test/language/for-of/head-expr-obj-iterator-method.js
 create mode 100644 test/language/for-of/head-expr-primitive-iterator-method.js
 create mode 100644 test/language/for-of/head-expr-to-obj.js
 create mode 100644 test/language/for-of/iterator-as-proxy.js
 create mode 100644 test/language/for-of/iterator-next-reference.js
 create mode 100644 test/language/for-of/iterator-next-result-done-attr.js
 create mode 100644 test/language/for-of/iterator-next-result-type.js
 create mode 100644 test/language/for-of/iterator-next-result-value-attr.js
 create mode 100644 test/language/for-of/nested.js
 create mode 100644 test/language/for-of/return.js

diff --git a/test/language/for-of/break-from-catch.js b/test/language/for-of/break-from-catch.js
new file mode 100644
index 0000000000..b3ef56b0fd
--- /dev/null
+++ b/test/language/for-of/break-from-catch.js
@@ -0,0 +1,29 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.n
+description: >
+    Control flow during body evaluation should honor `break` statements within
+    the `catch` block of `try` statements.
+---*/
+
+function* values() {
+  yield 1;
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+
+for (var x of iterable) {
+  i++;
+
+  try {
+    throw new Error();
+  } catch (err) {
+    break;
+  }
+
+  $ERROR('This code is unreachable.');
+}
+
+assert.sameValue(i, 1);
diff --git a/test/language/for-of/break-from-try.js b/test/language/for-of/break-from-try.js
new file mode 100644
index 0000000000..795b671bdb
--- /dev/null
+++ b/test/language/for-of/break-from-try.js
@@ -0,0 +1,28 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.n
+description: >
+    Control flow during body evaluation should honor `break` statements within
+    `try` blocks.
+---*/
+
+function* values() {
+  yield 1;
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+
+for (var x of iterable) {
+  i++;
+
+  try {
+    break;
+    $ERROR('This code is unreachable.');
+  } catch (err) {}
+
+  $ERROR('This code is unreachable.');
+}
+
+assert.sameValue(i, 1);
diff --git a/test/language/for-of/break-label.js b/test/language/for-of/break-label.js
new file mode 100644
index 0000000000..30d3c6737d
--- /dev/null
+++ b/test/language/for-of/break-label.js
@@ -0,0 +1,28 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.n
+description: >
+    Control flow during body evaluation should honor labeled `break`
+    statements.
+---*/
+
+function* values() {
+  yield 1;
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+
+outer:
+while (true) {
+  for (var x of iterable) {
+    i++;
+    break outer;
+
+    $ERROR('This code is unreachable.');
+  }
+  $ERROR('This code is unreachable.');
+}
+
+assert.sameValue(i, 1);
diff --git a/test/language/for-of/break.js b/test/language/for-of/break.js
new file mode 100644
index 0000000000..89bfc6bc42
--- /dev/null
+++ b/test/language/for-of/break.js
@@ -0,0 +1,23 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.n
+description: >
+    Control flow during body evaluation should honor `break` statements.
+---*/
+
+function* values() {
+  yield 1;
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+
+for (var x of iterable) {
+  i++;
+  break;
+
+  $ERROR('This code is unreachable.');
+}
+
+assert.sameValue(i, 1);
diff --git a/test/language/for-of/continue-from-catch.js b/test/language/for-of/continue-from-catch.js
new file mode 100644
index 0000000000..5a3a6ebab5
--- /dev/null
+++ b/test/language/for-of/continue-from-catch.js
@@ -0,0 +1,28 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.n
+description: >
+    Control flow during body evaluation should honor `continue` statements
+    within the `catch` block of `try` statements.
+---*/
+
+function* values() {
+  yield 1;
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+
+for (var x of iterable) {
+  i++;
+  try {
+    throw new Error();
+  } catch (err) {
+    continue;
+  }
+
+  $ERROR('This code is unreachable.');
+}
+
+assert.sameValue(i, 2);
diff --git a/test/language/for-of/continue-from-try.js b/test/language/for-of/continue-from-try.js
new file mode 100644
index 0000000000..0378fba7f4
--- /dev/null
+++ b/test/language/for-of/continue-from-try.js
@@ -0,0 +1,27 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.n
+description: >
+    Control flow during body evaluation should honor `continue` statements
+    within `try` blocks.
+---*/
+
+function* values() {
+  yield 1;
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+
+for (var x of iterable) {
+  i++;
+  try {
+    continue;
+    $ERROR('This code is unreachable.');
+  } catch (err) {}
+
+  $ERROR('This code is unreachable.');
+}
+
+assert.sameValue(i, 2);
diff --git a/test/language/for-of/continue-label.js b/test/language/for-of/continue-label.js
new file mode 100644
index 0000000000..760b9dbcf3
--- /dev/null
+++ b/test/language/for-of/continue-label.js
@@ -0,0 +1,30 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.n
+description: >
+    Control flow during body evaluation should honor labeled `continue`
+    statements.
+---*/
+
+function* values() {
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+var loop = true;
+
+outer:
+while (loop) {
+  loop = false;
+
+  for (var x of iterable) {
+    i++;
+    continue outer;
+
+    $ERROR('This code is unreachable (inside for-of).');
+  }
+  $ERROR('This code is unreachable (inside while).');
+}
+
+assert.sameValue(i, 1);
diff --git a/test/language/for-of/continue.js b/test/language/for-of/continue.js
new file mode 100644
index 0000000000..571377e924
--- /dev/null
+++ b/test/language/for-of/continue.js
@@ -0,0 +1,23 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.n
+description: >
+    Control flow during body evaluation should honor `continue` statements.
+---*/
+
+function* values() {
+  yield 1;
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+
+for (var x of iterable) {
+  i++;
+  continue;
+
+  $ERROR('This code is unreachable.');
+}
+
+assert.sameValue(i, 2);
diff --git a/test/language/for-of/generator.js b/test/language/for-of/generator.js
new file mode 100644
index 0000000000..7d0a5af27e
--- /dev/null
+++ b/test/language/for-of/generator.js
@@ -0,0 +1,23 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13
+description: >
+    Generator function should return valid iterable objects.
+---*/
+
+function* values() {
+  yield 2;
+  yield 4;
+  yield 8;
+}
+var iterable = values();
+var expected = [2, 4, 8];
+var i = 0;
+
+for (var x of iterable) {
+  assert.sameValue(x, expected[i]);
+  i++;
+}
+
+assert.sameValue(i, 3);
diff --git a/test/language/for-of/generic-iterable.js b/test/language/for-of/generic-iterable.js
new file mode 100644
index 0000000000..96cdd40271
--- /dev/null
+++ b/test/language/for-of/generic-iterable.js
@@ -0,0 +1,27 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13
+description: >
+    Generic objects with `@@iterator` protocols should function as iterables.
+---*/
+
+var iterable = {};
+iterable[Symbol.iterator] = function() {
+  var j = 0;
+  return {
+    next: function() {
+      j = j + 2;
+      return { value: j, done: j === 8 };
+    }
+  }
+};
+var expected = [2, 4, 6];
+var i = 0;
+
+for (var x of iterable) {
+  assert.sameValue(x, expected[i]);
+  i++;
+}
+
+assert.sameValue(i, 3);
diff --git a/test/language/for-of/head-expr-obj-iterator-method.js b/test/language/for-of/head-expr-obj-iterator-method.js
new file mode 100644
index 0000000000..20b4dc6ae0
--- /dev/null
+++ b/test/language/for-of/head-expr-obj-iterator-method.js
@@ -0,0 +1,13 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.12 S8.b
+description: >
+    The value of the expression in a for-of statement's head must have an
+    `@@iterator` method.
+---*/
+var x;
+
+assert.throws(TypeError, function() {
+  for (x of {}) {}
+});
diff --git a/test/language/for-of/head-expr-primitive-iterator-method.js b/test/language/for-of/head-expr-primitive-iterator-method.js
new file mode 100644
index 0000000000..0c7abe9bee
--- /dev/null
+++ b/test/language/for-of/head-expr-primitive-iterator-method.js
@@ -0,0 +1,17 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.12 S8.b
+description: >
+    The value of the expression in a for-of statement's head must have an
+    `@@iterator` method.
+---*/
+var x;
+
+assert.throws(TypeError, function() {
+  for (x of false) {}
+});
+
+assert.throws(TypeError, function() {
+  for (x of 37) {}
+});
diff --git a/test/language/for-of/head-expr-to-obj.js b/test/language/for-of/head-expr-to-obj.js
new file mode 100644
index 0000000000..085ca18308
--- /dev/null
+++ b/test/language/for-of/head-expr-to-obj.js
@@ -0,0 +1,17 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.12 S8.b
+description: >
+    The value of the expression in a for-of statement's head is subject to the
+    semantics of the ToObject abstract operation.
+---*/
+var x;
+
+assert.throws(TypeError, function() {
+  for (x of null) {}
+});
+
+assert.throws(TypeError, function() {
+  for (x of undefined) {}
+});
diff --git a/test/language/for-of/iterator-as-proxy.js b/test/language/for-of/iterator-as-proxy.js
new file mode 100644
index 0000000000..c9b975d414
--- /dev/null
+++ b/test/language/for-of/iterator-as-proxy.js
@@ -0,0 +1,35 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13
+description: >
+    Iterators that are implemented as proxies should behave identically to
+    non-proxy versions.
+---*/
+
+var iterable = {};
+var nextResult = { value: 23, done: false };
+var lastResult = { value: null, done: true };
+var i;
+
+var iterator = {
+  next: function() {
+    var result = nextResult;
+    nextResult = lastResult;
+    return result;
+  }
+};
+var proxiedIterator = new Proxy(iterator, {
+  get: function(target, name) {
+    return target[name];
+  }
+});
+iterable[Symbol.iterator] = function() { return proxiedIterator; };
+
+i = 0;
+for (var x of iterable) {
+  assert.sameValue(x, 23);
+  i++;
+}
+
+assert.sameValue(i, 1);
diff --git a/test/language/for-of/iterator-next-reference.js b/test/language/for-of/iterator-next-reference.js
new file mode 100644
index 0000000000..8770b406d5
--- /dev/null
+++ b/test/language/for-of/iterator-next-reference.js
@@ -0,0 +1,40 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.c
+description: >
+    The iterator's `next` method should be accessed with each iteration as per
+    the `IteratorStep` abstract operation (7.4.5).
+---*/
+
+var iterable = {};
+var iterator = {};
+var firstIterResult = { done: false };
+var iterationCount, invocationCount;
+
+iterable[Symbol.iterator] = function() {
+  return iterator;
+};
+
+iterator.next = function() { return { value: 45, done: false }; };
+iterationCount = 0;
+invocationCount = 0;
+for (var x of iterable) {
+  assert.sameValue(x, 45);
+
+  iterator.next = function() {
+    invocationCount++;
+
+    Object.defineProperty(iterator, 'next', {
+      get: function() {
+        $ERROR('Should not access the `next` method after iteration ' +
+          'is complete.');
+      }
+    });
+
+    return { value: null, done: true };
+  };
+  iterationCount++;
+}
+assert.sameValue(iterationCount, 1);
+assert.sameValue(invocationCount, 1);
diff --git a/test/language/for-of/iterator-next-result-done-attr.js b/test/language/for-of/iterator-next-result-done-attr.js
new file mode 100644
index 0000000000..50c9f414cd
--- /dev/null
+++ b/test/language/for-of/iterator-next-result-done-attr.js
@@ -0,0 +1,129 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 7.4.3
+description: >
+    The `done` value of iteration result objects should be interpreted as
+    incomplete as per `ToBoolean` (7.1.2).
+---*/
+
+var iterable = {};
+var i, firstIterResult;
+
+iterable[Symbol.iterator] = function() {
+  var finalIterResult = { value: null, done: true };
+  var nextIterResult = firstIterResult;
+
+  return {
+    next: function() {
+      var iterResult = nextIterResult;
+
+      nextIterResult = finalIterResult;
+
+      return iterResult;
+    }
+  };
+};
+
+firstIterResult = { value: null, done: undefined };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { value: null };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { value: null, done: null };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { value: null, done: false };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { value: null, done: true };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 0);
+
+firstIterResult = { value: null, done: 1 };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 0);
+
+firstIterResult = { value: null, done: 0 };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { value: null, done: -0 };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { value: null, done: NaN };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { value: null, done: '' };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { value: null, done: '0' };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 0);
+
+firstIterResult = { value: null, done: Symbol() };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 0);
+
+firstIterResult = { value: null, done: {} };
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 0);
+
+firstIterResult = { value: null };
+Object.defineProperty(firstIterResult, 'done', {
+  get: function() {
+    return true;
+  }
+});
+i = 0;
+for (var x of iterable) {
+  i++;
+}
+assert.sameValue(i, 0);
diff --git a/test/language/for-of/iterator-next-result-type.js b/test/language/for-of/iterator-next-result-type.js
new file mode 100644
index 0000000000..351ce1b97a
--- /dev/null
+++ b/test/language/for-of/iterator-next-result-type.js
@@ -0,0 +1,105 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.c
+description: >
+    If Type(result) is not Object, throw a TypeError exception as per
+    `IteratorNext` (7.4.2 S4)
+---*/
+
+var iterable = {};
+var firstIterResult;
+
+iterable[Symbol.iterator] = function() {
+  var finalIterResult = { value: null, done: true };
+  var nextIterResult = firstIterResult;
+
+  return {
+    next: function() {
+      var iterResult = nextIterResult;
+
+      nextIterResult = finalIterResult;
+
+      return iterResult;
+    }
+  };
+};
+
+firstIterResult = true;
+assert.throws(TypeError, function() {
+  for (var x of iterable) {}
+});
+
+firstIterResult = false;
+assert.throws(TypeError, function() {
+  for (var x of iterable) {}
+});
+
+firstIterResult = 'string';
+assert.throws(TypeError, function() {
+  for (var x of iterable) {}
+});
+
+firstIterResult = undefined;
+assert.throws(TypeError, function() {
+  for (var x of iterable) {}
+});
+
+firstIterResult = null;
+assert.throws(TypeError, function() {
+  for (var x of iterable) {}
+});
+
+firstIterResult = 4;
+assert.throws(TypeError, function() {
+  for (var x of iterable) {}
+});
+
+firstIterResult = NaN;
+assert.throws(TypeError, function() {
+  for (var x of iterable) {}
+});
+
+firstIterResult = Symbol('s');
+assert.throws(TypeError, function() {
+  for (var x of iterable) {}
+});
+
+firstIterResult = /regexp/;
+for (var x of iterable) {}
+
+firstIterResult = {};
+for (var x of iterable) {}
+
+firstIterResult = new Proxy({}, {
+  get: function(receiver, name) {
+    if (name === 'done') {
+      return true;
+    }
+    if (name === 'value') {
+      return null;
+    }
+    $ERROR('This code is unreachable.');
+  }
+});
+for (var x of iterable) {
+  $ERROR('This code is unreachable.');
+}
+
+firstIterResult = new Proxy({}, {
+  get: function(receiver, name) {
+    if (name === 'done') {
+      return false;
+    }
+    if (name === 'value') {
+      return 23;
+    }
+    $ERROR('This code is unreachable.');
+  }
+});
+i = 0;
+for (var x of iterable) {
+  assert.sameValue(x, 23);
+  i++;
+}
+assert.sameValue(i, 1);
diff --git a/test/language/for-of/iterator-next-result-value-attr.js b/test/language/for-of/iterator-next-result-value-attr.js
new file mode 100644
index 0000000000..1afda16b1d
--- /dev/null
+++ b/test/language/for-of/iterator-next-result-value-attr.js
@@ -0,0 +1,47 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13 S5.c
+description: >
+    The `done` value of iteration result objects should be interpreted as
+    incomplete as per `ToBoolean` (7.1.2).
+---*/
+
+var iterable = {};
+var i, firstIterResult;
+
+iterable[Symbol.iterator] = function() {
+  var finalIterResult = { value: null, done: true };
+  var nextIterResult = firstIterResult;
+
+  return {
+    next: function() {
+      var iterResult = nextIterResult;
+
+      nextIterResult = finalIterResult;
+
+      return iterResult;
+    }
+  };
+};
+
+firstIterResult = { value: 45, done: false };
+i = 0;
+for (var x of iterable) {
+  assert.sameValue(x, 45);
+  i++;
+}
+assert.sameValue(i, 1);
+
+firstIterResult = { done: false };
+Object.defineProperty(firstIterResult, 'value', {
+  get: function() {
+    return 23;
+  }
+});
+i = 0;
+for (var x of iterable) {
+  assert.sameValue(x, 23);
+  i++;
+}
+assert.sameValue(i, 1);
diff --git a/test/language/for-of/nested.js b/test/language/for-of/nested.js
new file mode 100644
index 0000000000..eedfbda798
--- /dev/null
+++ b/test/language/for-of/nested.js
@@ -0,0 +1,37 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13
+description: >
+    Nested statements should operate independently.
+---*/
+
+function* values() {
+  yield 3;
+  yield 7;
+}
+
+var outerIterable, expectedOuter, i, innerIterable, expectedInner, j;
+
+outerIterable = values();
+expectedOuter = 3;
+i = 0;
+
+for (var x of outerIterable) {
+  assert.sameValue(x, expectedOuter);
+  expectedOuter = 7;
+  i++;
+
+  innerIterable = values();
+  expectedInner = 3;
+  j = 0;
+  for (var y of innerIterable) {
+    assert.sameValue(y, expectedInner);
+    expectedInner = 7;
+    j++;
+  }
+
+  assert.sameValue(j, 2);
+}
+
+assert.sameValue(i, 2);
diff --git a/test/language/for-of/return.js b/test/language/for-of/return.js
new file mode 100644
index 0000000000..b849d0ba58
--- /dev/null
+++ b/test/language/for-of/return.js
@@ -0,0 +1,28 @@
+// Copyright (C) Copyright 2013 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 13.6.4.13
+description: >
+    Control flow during body evaluation should honor `return` statements.
+---*/
+
+function* values() {
+  yield 1;
+  yield 1;
+}
+var iterable = values();
+var i = 0;
+
+var result = (function() {
+  for (var x of iterable) {
+    i++;
+    return 34;
+
+    $ERROR('This code is unreachable.');
+  }
+
+  $ERROR('This code is unreachable.');
+})();
+
+assert.sameValue(result, 34);
+assert.sameValue(i, 1);
-- 
GitLab