summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/generators/yield-star-iterator-close.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/non262/generators/yield-star-iterator-close.js')
-rw-r--r--js/src/tests/non262/generators/yield-star-iterator-close.js153
1 files changed, 153 insertions, 0 deletions
diff --git a/js/src/tests/non262/generators/yield-star-iterator-close.js b/js/src/tests/non262/generators/yield-star-iterator-close.js
new file mode 100644
index 0000000000..91ad31cb64
--- /dev/null
+++ b/js/src/tests/non262/generators/yield-star-iterator-close.js
@@ -0,0 +1,153 @@
+// Tests that the "return" method on iterators is called in yield*
+// expressions.
+
+function test() {
+ var returnCalled = 0;
+ var returnCalledExpected = 0;
+ var nextCalled = 0;
+ var nextCalledExpected = 0;
+ var throwCalled = 0;
+ var throwCalledExpected = 0;
+ var iterable = {};
+ iterable[Symbol.iterator] = makeIterator({
+ next: function() {
+ nextCalled++;
+ return { done: false };
+ },
+ ret: function() {
+ returnCalled++;
+ return { done: true, value: "iter.return" };
+ }
+ });
+
+ function* y() {
+ yield* iterable;
+ }
+
+ // G.p.throw on an iterator without "throw" calls IteratorClose.
+ var g1 = y();
+ g1.next();
+ assertThrowsInstanceOf(function() {
+ g1.throw("foo");
+ }, TypeError);
+ assertEq(returnCalled, ++returnCalledExpected);
+ assertEq(nextCalled, ++nextCalledExpected);
+ g1.next();
+ assertEq(nextCalled, nextCalledExpected);
+
+ // G.p.return calls "return", and if the result.done is true, return the
+ // result.
+ var g2 = y();
+ g2.next();
+ var v2 = g2.return("test return");
+ assertEq(v2.done, true);
+ assertEq(v2.value, "iter.return");
+ assertEq(returnCalled, ++returnCalledExpected);
+ assertEq(nextCalled, ++nextCalledExpected);
+ g2.next();
+ assertEq(nextCalled, nextCalledExpected);
+
+ // G.p.return calls "return", and if the result.done is false, continue
+ // yielding.
+ iterable[Symbol.iterator] = makeIterator({
+ next: function() {
+ nextCalled++;
+ return { done: false };
+ },
+ ret: function() {
+ returnCalled++;
+ return { done: false, value: "iter.return" };
+ }
+ });
+ var g3 = y();
+ g3.next();
+ var v3 = g3.return("test return");
+ assertEq(v3.done, false);
+ assertEq(v3.value, "iter.return");
+ assertEq(returnCalled, ++returnCalledExpected);
+ assertEq(nextCalled, ++nextCalledExpected);
+ g3.next();
+ assertEq(nextCalled, ++nextCalledExpected);
+
+ // G.p.return throwing does not re-call iter.return.
+ iterable[Symbol.iterator] = makeIterator({
+ ret: function() {
+ returnCalled++;
+ throw "in iter.return";
+ }
+ });
+ var g4 = y();
+ g4.next();
+ assertThrowsValue(function() {
+ g4.return("in test");
+ }, "in iter.return");
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // G.p.return expects iter.return to return an Object.
+ iterable[Symbol.iterator] = makeIterator({
+ ret: function() {
+ returnCalled++;
+ return 42;
+ }
+ });
+ var g5 = y();
+ g5.next();
+ assertThrowsInstanceOf(function() {
+ g5.return("foo");
+ }, TypeError);
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // IteratorClose expects iter.return to return an Object.
+ var g6 = y();
+ g6.next();
+ var exc;
+ try {
+ g6.throw("foo");
+ } catch (e) {
+ exc = e;
+ } finally {
+ assertEq(exc instanceof TypeError, true);
+ // The message test is here because instanceof TypeError doesn't
+ // distinguish the non-Object return TypeError and the
+ // throw-method-is-not-defined iterator protocol error.
+ assertEq(exc.toString().indexOf("non-object") > 0, true);
+ }
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // G.p.return passes its argument to "return".
+ iterable[Symbol.iterator] = makeIterator({
+ ret: function(x) {
+ assertEq(x, "in test");
+ returnCalled++;
+ return { done: true };
+ }
+ });
+ var g7 = y();
+ g7.next();
+ g7.return("in test");
+ assertEq(returnCalled, ++returnCalledExpected);
+
+ // If a throw method is present, do not call "return".
+ iterable[Symbol.iterator] = makeIterator({
+ throw: function(e) {
+ throwCalled++;
+ throw e;
+ },
+ ret: function(x) {
+ returnCalled++;
+ return { done: true };
+ }
+ });
+ var g8 = y();
+ g8.next();
+ assertThrowsValue(function() {
+ g8.throw("foo");
+ }, "foo");
+ assertEq(throwCalled, ++throwCalledExpected);
+ assertEq(returnCalled, returnCalledExpected);
+}
+
+test();
+
+if (typeof reportCompare === "function")
+ reportCompare(0, 0);