summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/Statements/for-of-iterator-close.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_6/Statements/for-of-iterator-close.js')
-rw-r--r--js/src/tests/ecma_6/Statements/for-of-iterator-close.js102
1 files changed, 102 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Statements/for-of-iterator-close.js b/js/src/tests/ecma_6/Statements/for-of-iterator-close.js
new file mode 100644
index 000000000..b28895d8f
--- /dev/null
+++ b/js/src/tests/ecma_6/Statements/for-of-iterator-close.js
@@ -0,0 +1,102 @@
+// Tests that IteratorReturn is called when a for-of loop has an abrupt
+// completion value during non-iterator code.
+
+function test() {
+ var returnCalled = 0;
+ var returnCalledExpected = 0;
+ var iterable = {};
+ iterable[Symbol.iterator] = makeIterator({
+ ret: function() {
+ returnCalled++;
+ return {};
+ }
+ });
+
+ // break calls iter.return
+ for (var x of iterable)
+ break;
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // throw in body calls iter.return
+ assertThrowsValue(function() {
+ for (var x of iterable)
+ throw "in body";
+ }, "in body");
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // throw in lhs ref calls iter.return
+ function throwlhs() {
+ throw "in lhs";
+ }
+ assertThrowsValue(function() {
+ for ((throwlhs()) of iterable)
+ continue;
+ }, "in lhs");
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // throw in iter.return doesn't re-call iter.return
+ iterable[Symbol.iterator] = makeIterator({
+ ret: function() {
+ returnCalled++;
+ throw "in iter.return";
+ }
+ });
+ assertThrowsValue(function() {
+ for (var x of iterable)
+ break;
+ }, "in iter.return");
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // throw in iter.next doesn't call IteratorClose
+ iterable[Symbol.iterator] = makeIterator({
+ next: function() {
+ throw "in next";
+ }
+ });
+ assertThrowsValue(function() {
+ for (var x of iterable)
+ break;
+ }, "in next");
+ assertEq(returnCalled, returnCalledExpected);
+
+ // "return" must return an Object.
+ iterable[Symbol.iterator] = makeIterator({
+ ret: function() {
+ returnCalled++;
+ return 42;
+ }
+ });
+ assertThrowsInstanceOf(function() {
+ for (var x of iterable)
+ break;
+ }, TypeError);
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // continue doesn't call iter.return for the loop it's continuing
+ var i = 0;
+ iterable[Symbol.iterator] = makeIterator({
+ next: function() {
+ return { done: i++ > 5 };
+ },
+ ret: function() {
+ returnCalled++;
+ return {};
+ }
+ });
+ for (var x of iterable)
+ continue;
+ assertEq(returnCalled, returnCalledExpected);
+
+ // continue does call iter.return for loops it skips
+ i = 0;
+ L: do {
+ for (var x of iterable)
+ continue L;
+ } while (false);
+ assertEq(returnCalled, ++returnCalledExpected);
+}
+
+test();
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);