summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/Generators/iteration.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/ecma_6/Generators/iteration.js')
-rw-r--r--js/src/tests/ecma_6/Generators/iteration.js574
1 files changed, 574 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Generators/iteration.js b/js/src/tests/ecma_6/Generators/iteration.js
new file mode 100644
index 000000000..6eb6a51aa
--- /dev/null
+++ b/js/src/tests/ecma_6/Generators/iteration.js
@@ -0,0 +1,574 @@
+// This file was written by Andy Wingo <wingo@igalia.com> and originally
+// contributed to V8 as generators-objects.js, available here:
+//
+// http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/harmony/generators-objects.js
+
+// Test aspects of the generator runtime.
+
+
+var GeneratorFunction = (function*(){yield 1;}).constructor;
+
+
+function TestGeneratorResultPrototype() {
+ function* g() { yield 1; }
+ var iter = g();
+ assertIteratorNext(iter, 1);
+ assertIteratorDone(iter, undefined);
+ assertIteratorDone(iter, undefined);
+}
+TestGeneratorResultPrototype();
+
+function TestGenerator(g, expected_values_for_next,
+ send_val, expected_values_for_send) {
+ function testNext(thunk) {
+ var iter = thunk();
+ for (var i = 0; i < expected_values_for_next.length; i++) {
+ assertIteratorResult(iter.next(), expected_values_for_next[i],
+ i == expected_values_for_next.length - 1);
+ }
+ assertIteratorDone(iter, undefined);
+ }
+ function testSend(thunk) {
+ var iter = thunk();
+ for (var i = 0; i < expected_values_for_send.length; i++) {
+ assertIteratorResult(iter.next(send_val),
+ expected_values_for_send[i],
+ i == expected_values_for_send.length - 1);
+ }
+ assertIteratorDone(iter, undefined);
+ }
+ function testThrow(thunk) {
+ for (var i = 0; i < expected_values_for_next.length; i++) {
+ var iter = thunk();
+ for (var j = 0; j < i; j++) {
+ assertIteratorResult(iter.next(),
+ expected_values_for_next[j],
+ j == expected_values_for_next.length - 1);
+ }
+ var Sentinel = function () {}
+ assertThrowsInstanceOf(function () { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ }
+
+ testNext(g);
+ testSend(g);
+ testThrow(g);
+
+ testNext(function*() { return yield* g(); });
+ testSend(function*() { return yield* g(); });
+ testThrow(function*() { return yield* g(); });
+
+ if (g instanceof GeneratorFunction) {
+ testNext(function() { return g(); });
+ testSend(function() { return g(); });
+ testThrow(function() { return g(); });
+ }
+}
+
+TestGenerator(function* g1() { },
+ [undefined],
+ "foo",
+ [undefined]);
+
+TestGenerator(function* g2() { yield 1; },
+ [1, undefined],
+ "foo",
+ [1, undefined]);
+
+TestGenerator(function* g3() { yield 1; yield 2; },
+ [1, 2, undefined],
+ "foo",
+ [1, 2, undefined]);
+
+TestGenerator(function* g4() { yield 1; yield 2; return 3; },
+ [1, 2, 3],
+ "foo",
+ [1, 2, 3]);
+
+TestGenerator(function* g5() { return 1; },
+ [1],
+ "foo",
+ [1]);
+
+TestGenerator(function* g6() { var x = yield 1; return x; },
+ [1, undefined],
+ "foo",
+ [1, "foo"]);
+
+TestGenerator(function* g7() { var x = yield 1; yield 2; return x; },
+ [1, 2, undefined],
+ "foo",
+ [1, 2, "foo"]);
+
+TestGenerator(function* g8() { for (var x = 0; x < 4; x++) { yield x; } },
+ [0, 1, 2, 3, undefined],
+ "foo",
+ [0, 1, 2, 3, undefined]);
+
+// Generator with arguments.
+TestGenerator(
+ function g9() {
+ return (function*(a, b, c, d) {
+ yield a; yield b; yield c; yield d;
+ })("fee", "fi", "fo", "fum");
+ },
+ ["fee", "fi", "fo", "fum", undefined],
+ "foo",
+ ["fee", "fi", "fo", "fum", undefined]);
+
+// Too few arguments.
+TestGenerator(
+ function g10() {
+ return (function*(a, b, c, d) {
+ yield a; yield b; yield c; yield d;
+ })("fee", "fi");
+ },
+ ["fee", "fi", undefined, undefined, undefined],
+ "foo",
+ ["fee", "fi", undefined, undefined, undefined]);
+
+// Too many arguments.
+TestGenerator(
+ function g11() {
+ return (function*(a, b, c, d) {
+ yield a; yield b; yield c; yield d;
+ })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman");
+ },
+ ["fee", "fi", "fo", "fum", undefined],
+ "foo",
+ ["fee", "fi", "fo", "fum", undefined]);
+
+// The arguments object.
+TestGenerator(
+ function g12() {
+ return (function*(a, b, c, d) {
+ for (var i = 0; i < arguments.length; i++) {
+ yield arguments[i];
+ }
+ })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman");
+ },
+ ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman",
+ undefined],
+ "foo",
+ ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman",
+ undefined]);
+
+// Access to captured free variables.
+TestGenerator(
+ function g13() {
+ return (function(a, b, c, d) {
+ return (function*() {
+ yield a; yield b; yield c; yield d;
+ })();
+ })("fee", "fi", "fo", "fum");
+ },
+ ["fee", "fi", "fo", "fum", undefined],
+ "foo",
+ ["fee", "fi", "fo", "fum", undefined]);
+
+// Abusing the arguments object.
+TestGenerator(
+ function g14() {
+ return (function*(a, b, c, d) {
+ arguments[0] = "Be he live";
+ arguments[1] = "or be he dead";
+ arguments[2] = "I'll grind his bones";
+ arguments[3] = "to make my bread";
+ yield a; yield b; yield c; yield d;
+ })("fee", "fi", "fo", "fum");
+ },
+ ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread",
+ undefined],
+ "foo",
+ ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread",
+ undefined]);
+
+// Abusing the arguments object: strict mode.
+TestGenerator(
+ function g15() {
+ return (function*(a, b, c, d) {
+ "use strict";
+ arguments[0] = "Be he live";
+ arguments[1] = "or be he dead";
+ arguments[2] = "I'll grind his bones";
+ arguments[3] = "to make my bread";
+ yield a; yield b; yield c; yield d;
+ })("fee", "fi", "fo", "fum");
+ },
+ ["fee", "fi", "fo", "fum", undefined],
+ "foo",
+ ["fee", "fi", "fo", "fum", undefined]);
+
+// GC.
+if (typeof gc == 'function') {
+ TestGenerator(function* g16() { yield "baz"; gc(); yield "qux"; },
+ ["baz", "qux", undefined],
+ "foo",
+ ["baz", "qux", undefined]);
+}
+
+// Receivers.
+TestGenerator(
+ function g17() {
+ function* g() { yield this.x; yield this.y; }
+ var o = { start: g, x: 1, y: 2 };
+ return o.start();
+ },
+ [1, 2, undefined],
+ "foo",
+ [1, 2, undefined]);
+
+// FIXME: Capture the generator object as "this" in new g(). Bug 907742.
+// TestGenerator(
+// function g18() {
+// function* g() { yield this.x; yield this.y; }
+// var iter = new g;
+// iter.x = 1;
+// iter.y = 2;
+// return iter;
+// },
+// [1, 2, undefined],
+// "foo",
+// [1, 2, undefined]);
+
+TestGenerator(
+ function* g19() {
+ var x = 1;
+ yield x;
+ with({x:2}) { yield x; }
+ yield x;
+ },
+ [1, 2, 1, undefined],
+ "foo",
+ [1, 2, 1, undefined]);
+
+TestGenerator(
+ function* g20() { yield (1 + (yield 2) + 3); },
+ [2, NaN, undefined],
+ "foo",
+ [2, "1foo3", undefined]);
+
+TestGenerator(
+ function* g21() { return (1 + (yield 2) + 3); },
+ [2, NaN],
+ "foo",
+ [2, "1foo3"]);
+
+TestGenerator(
+ function* g22() { yield (1 + (yield 2) + 3); yield (4 + (yield 5) + 6); },
+ [2, NaN, 5, NaN, undefined],
+ "foo",
+ [2, "1foo3", 5, "4foo6", undefined]);
+
+TestGenerator(
+ function* g23() {
+ return (yield (1 + (yield 2) + 3)) + (yield (4 + (yield 5) + 6));
+ },
+ [2, NaN, 5, NaN, NaN],
+ "foo",
+ [2, "1foo3", 5, "4foo6", "foofoo"]);
+
+// Rewind a try context with and without operands on the stack.
+TestGenerator(
+ function* g24() {
+ try {
+ return (yield (1 + (yield 2) + 3)) + (yield (4 + (yield 5) + 6));
+ } catch (e) {
+ throw e;
+ }
+ },
+ [2, NaN, 5, NaN, NaN],
+ "foo",
+ [2, "1foo3", 5, "4foo6", "foofoo"]);
+
+// Yielding in a catch context, with and without operands on the stack.
+TestGenerator(
+ function* g25() {
+ try {
+ throw (yield (1 + (yield 2) + 3))
+ } catch (e) {
+ if (typeof e == 'object') throw e;
+ return e + (yield (4 + (yield 5) + 6));
+ }
+ },
+ [2, NaN, 5, NaN, NaN],
+ "foo",
+ [2, "1foo3", 5, "4foo6", "foofoo"]);
+
+// Generator function instances.
+TestGenerator(GeneratorFunction(),
+ [undefined],
+ "foo",
+ [undefined]);
+
+TestGenerator(new GeneratorFunction(),
+ [undefined],
+ "foo",
+ [undefined]);
+
+TestGenerator(GeneratorFunction('yield 1;'),
+ [1, undefined],
+ "foo",
+ [1, undefined]);
+
+TestGenerator(
+ function() { return GeneratorFunction('x', 'y', 'yield x + y;')(1, 2) },
+ [3, undefined],
+ "foo",
+ [3, undefined]);
+
+// Access to this with formal arguments.
+TestGenerator(
+ function () {
+ return ({ x: 42, g: function* (a) { yield this.x } }).g(0);
+ },
+ [42, undefined],
+ "foo",
+ [42, undefined]);
+
+function TestTryCatch(instantiate) {
+ function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; }
+ function Sentinel() {}
+
+ function Test1(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ assertIteratorNext(iter, 3);
+ assertIteratorDone(iter, undefined);
+ assertIteratorDone(iter, undefined);
+ }
+ Test1(instantiate(g));
+
+ function Test2(iter) {
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test2(instantiate(g));
+
+ function Test3(iter) {
+ assertIteratorNext(iter, 1);
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test3(instantiate(g));
+
+ function Test4(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ var exn = new Sentinel;
+ assertIteratorResult(iter.throw(exn), exn, false);
+ assertIteratorNext(iter, 3);
+ assertIteratorDone(iter, undefined);
+ assertIteratorDone(iter, undefined);
+ }
+ Test4(instantiate(g));
+
+ function Test5(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ var exn = new Sentinel;
+ assertIteratorResult(iter.throw(exn), exn, false);
+ assertIteratorNext(iter, 3);
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+
+ }
+ Test5(instantiate(g));
+
+ function Test6(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ var exn = new Sentinel;
+ assertIteratorResult(iter.throw(exn), exn, false);
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test6(instantiate(g));
+}
+TestTryCatch(function (g) { return g(); });
+TestTryCatch(function* (g) { return yield* g(); });
+
+function TestTryFinally(instantiate) {
+ function* g() { yield 1; try { yield 2; } finally { yield 3; } yield 4; }
+ function Sentinel() {}
+ function Sentinel2() {}
+
+ function Test1(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ assertIteratorNext(iter, 3);
+ assertIteratorNext(iter, 4);
+ assertIteratorDone(iter, undefined);
+ assertIteratorDone(iter, undefined);
+ }
+ Test1(instantiate(g));
+
+ function Test2(iter) {
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test2(instantiate(g));
+
+ function Test3(iter) {
+ assertIteratorNext(iter, 1);
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test3(instantiate(g));
+
+ function Test4(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ assertIteratorResult(iter.throw(new Sentinel), 3, false);
+ assertThrowsInstanceOf(function() { iter.next(); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+
+ }
+ Test4(instantiate(g));
+
+ function Test5(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ assertIteratorResult(iter.throw(new Sentinel), 3, false);
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel2); }, Sentinel2);
+ assertIteratorDone(iter, undefined);
+ }
+ Test5(instantiate(g));
+
+ function Test6(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ assertIteratorNext(iter, 3);
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test6(instantiate(g));
+
+ function Test7(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ assertIteratorNext(iter, 3);
+ assertIteratorNext(iter, 4);
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test7(instantiate(g));
+}
+TestTryFinally(function (g) { return g(); });
+TestTryFinally(function* (g) { return yield* g(); });
+
+function TestNestedTry(instantiate) {
+ function* g() {
+ try {
+ yield 1;
+ try { yield 2; } catch (e) { yield e; }
+ yield 3;
+ } finally {
+ yield 4;
+ }
+ yield 5;
+ }
+ function Sentinel() {}
+ function Sentinel2() {}
+
+ function Test1(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ assertIteratorNext(iter, 3);
+ assertIteratorNext(iter, 4);
+ assertIteratorNext(iter, 5);
+ assertIteratorDone(iter, undefined);
+ assertIteratorDone(iter, undefined);
+ }
+ Test1(instantiate(g));
+
+ function Test2(iter) {
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test2(instantiate(g));
+
+ function Test3(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorResult(iter.throw(new Sentinel), 4, false);
+ assertThrowsInstanceOf(function() { iter.next(); }, Sentinel);
+ assertIteratorDone(iter, undefined);
+ }
+ Test3(instantiate(g));
+
+ function Test4(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorResult(iter.throw(new Sentinel), 4, false);
+ assertThrowsInstanceOf(function() { iter.throw(new Sentinel2); }, Sentinel2);
+ assertIteratorDone(iter, undefined);
+ }
+ Test4(instantiate(g));
+
+ function Test5(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ var exn = new Sentinel;
+ assertIteratorResult(iter.throw(exn), exn, false);
+ assertIteratorNext(iter, 3);
+ assertIteratorNext(iter, 4);
+ assertIteratorNext(iter, 5);
+ assertIteratorDone(iter, undefined);
+ assertIteratorDone(iter, undefined);
+
+ }
+ Test5(instantiate(g));
+
+ function Test6(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ var exn = new Sentinel;
+ assertIteratorResult(iter.throw(exn), exn, false);
+ assertIteratorResult(iter.throw(new Sentinel2), 4, false);
+ assertThrowsInstanceOf(function() { iter.next(); }, Sentinel2);
+ assertIteratorDone(iter, undefined);
+ }
+ Test6(instantiate(g));
+
+ function Test7(iter) {
+ assertIteratorNext(iter, 1);
+ assertIteratorNext(iter, 2);
+ var exn = new Sentinel;
+ assertIteratorResult(iter.throw(exn), exn, false);
+ assertIteratorNext(iter, 3);
+ assertIteratorResult(iter.throw(new Sentinel2), 4, false);
+ assertThrowsInstanceOf(function() { iter.next(); }, Sentinel2);
+ assertIteratorDone(iter, undefined);
+
+ }
+ Test7(instantiate(g));
+
+ // That's probably enough.
+}
+TestNestedTry(function (g) { return g(); });
+TestNestedTry(function* (g) { return yield* g(); });
+
+function TestRecursion() {
+ function TestNextRecursion() {
+ function* g() { yield iter.next(); }
+ var iter = g();
+ return iter.next();
+ }
+ function TestSendRecursion() {
+ function* g() { yield iter.next(42); }
+ var iter = g();
+ return iter.next();
+ }
+ function TestThrowRecursion() {
+ function* g() { yield iter.throw(1); }
+ var iter = g();
+ return iter.next();
+ }
+ assertThrowsInstanceOf(TestNextRecursion, TypeError);
+ assertThrowsInstanceOf(TestSendRecursion, TypeError);
+ assertThrowsInstanceOf(TestThrowRecursion, TypeError);
+}
+TestRecursion();
+
+if (typeof reportCompare == "function")
+ reportCompare(true, true);