summaryrefslogtreecommitdiff
path: root/deps/v8/test/mjsunit/es6/generators-iteration.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/mjsunit/es6/generators-iteration.js')
-rw-r--r--deps/v8/test/mjsunit/es6/generators-iteration.js698
1 files changed, 698 insertions, 0 deletions
diff --git a/deps/v8/test/mjsunit/es6/generators-iteration.js b/deps/v8/test/mjsunit/es6/generators-iteration.js
new file mode 100644
index 0000000000..b6fcdaa487
--- /dev/null
+++ b/deps/v8/test/mjsunit/es6/generators-iteration.js
@@ -0,0 +1,698 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --expose-gc
+
+// Test generator iteration.
+
+var GeneratorFunction = (function*(){yield 1;}).__proto__.constructor;
+
+function assertIteratorResult(value, done, result) {
+ assertEquals({ value: value, done: done}, result);
+}
+
+function assertIteratorIsClosed(iter) {
+ assertIteratorResult(undefined, true, iter.next());
+ assertDoesNotThrow(function() { iter.next(); });
+}
+
+function assertThrownIteratorIsClosed(iter) {
+ // TODO(yusukesuzuki): Since status of a thrown generator is "executing",
+ // following tests are failed.
+ // https://code.google.com/p/v8/issues/detail?id=3096
+ // assertIteratorIsClosed(iter);
+}
+
+function TestGeneratorResultPrototype() {
+ function* g() { yield 1; }
+ var iter = g();
+ var result = iter.next();
+
+ assertSame(Object.prototype, Object.getPrototypeOf(result));
+ property_names = Object.getOwnPropertyNames(result);
+ property_names.sort();
+ assertEquals(["done", "value"], property_names);
+ assertIteratorResult(1, false, result);
+}
+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++) {
+ var v1 = expected_values_for_next[i];
+ var v2 = i == expected_values_for_next.length - 1;
+ // var v3 = iter.next();
+ assertIteratorResult(v1, v2, iter.next());
+ }
+ assertIteratorIsClosed(iter);
+ }
+ function testSend(thunk) {
+ var iter = thunk();
+ for (var i = 0; i < expected_values_for_send.length; i++) {
+ assertIteratorResult(expected_values_for_send[i],
+ i == expected_values_for_send.length - 1,
+ iter.next(send_val));
+ }
+ assertIteratorIsClosed(iter);
+ }
+ 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(expected_values_for_next[j],
+ j == expected_values_for_next.length - 1,
+ iter.next());
+ }
+ function Sentinel() {}
+ assertThrows(function () { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ }
+
+ 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 new g(); });
+ testSend(function() { return new g(); });
+ testThrow(function() { return new 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.
+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]);
+
+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"]);
+
+// Yield with no arguments yields undefined.
+TestGenerator(
+ function* g26() { return yield yield },
+ [undefined, undefined, undefined],
+ "foo",
+ [undefined, "foo", "foo"]);
+
+// A newline causes the parser to stop looking for an argument to yield.
+TestGenerator(
+ function* g27() {
+ yield
+ 3
+ return
+ },
+ [undefined, undefined],
+ "foo",
+ [undefined, undefined]);
+
+// TODO(wingo): We should use TestGenerator for these, except that
+// currently yield* will unconditionally propagate a throw() to the
+// delegate iterator, which fails for these iterators that don't have
+// throw(). See http://code.google.com/p/v8/issues/detail?id=3484.
+(function() {
+ function* g28() {
+ yield* [1, 2, 3];
+ }
+ var iter = g28();
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorResult(undefined, true, iter.next());
+})();
+
+(function() {
+ function* g29() {
+ yield* "abc";
+ }
+ var iter = g29();
+ assertIteratorResult("a", false, iter.next());
+ assertIteratorResult("b", false, iter.next());
+ assertIteratorResult("c", false, iter.next());
+ assertIteratorResult(undefined, true, iter.next());
+})();
+
+// 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]);
+
+// Test that yield* re-yields received results without re-boxing.
+function TestDelegatingYield() {
+ function results(results) {
+ var i = 0;
+ function next() {
+ return results[i++];
+ }
+ var iter = { next: next };
+ var ret = {};
+ ret[Symbol.iterator] = function() { return iter; };
+ return ret;
+ }
+ function* yield_results(expected) {
+ return yield* results(expected);
+ }
+ function collect_results(iterable) {
+ var iter = iterable[Symbol.iterator]();
+ var ret = [];
+ var result;
+ do {
+ result = iter.next();
+ ret.push(result);
+ } while (!result.done);
+ return ret;
+ }
+ // We have to put a full result for the end, because the return will re-box.
+ var expected = [{value: 1}, 13, "foo", {value: 34, done: true}];
+
+ // Sanity check.
+ assertEquals(expected, collect_results(results(expected)));
+ assertEquals(expected, collect_results(yield_results(expected)));
+}
+TestDelegatingYield();
+
+function TestTryCatch(instantiate) {
+ function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; }
+ function Sentinel() {}
+
+ function Test1(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorIsClosed(iter);
+ }
+ Test1(instantiate(g));
+
+ function Test2(iter) {
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test2(instantiate(g));
+
+ function Test3(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test3(instantiate(g));
+
+ function Test4(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ var exn = new Sentinel;
+ assertIteratorResult(exn, false, iter.throw(exn));
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorIsClosed(iter);
+ }
+ Test4(instantiate(g));
+
+ function Test5(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ var exn = new Sentinel;
+ assertIteratorResult(exn, false, iter.throw(exn));
+ assertIteratorResult(3, false, iter.next());
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test5(instantiate(g));
+
+ function Test6(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ var exn = new Sentinel;
+ assertIteratorResult(exn, false, iter.throw(exn));
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test6(instantiate(g));
+
+ function Test7(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorIsClosed(iter);
+ }
+ Test7(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) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorResult(4, false, iter.next());
+ assertIteratorIsClosed(iter);
+ }
+ Test1(instantiate(g));
+
+ function Test2(iter) {
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test2(instantiate(g));
+
+ function Test3(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test3(instantiate(g));
+
+ function Test4(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.throw(new Sentinel));
+ assertThrows(function() { iter.next(); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test4(instantiate(g));
+
+ function Test5(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.throw(new Sentinel));
+ assertThrows(function() { iter.throw(new Sentinel2); }, Sentinel2);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test5(instantiate(g));
+
+ function Test6(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test6(instantiate(g));
+
+ function Test7(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorResult(4, false, iter.next());
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test7(instantiate(g));
+
+ function Test8(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorResult(4, false, iter.next());
+ assertIteratorIsClosed(iter);
+ }
+ Test8(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) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorResult(4, false, iter.next());
+ assertIteratorResult(5, false, iter.next());
+ assertIteratorIsClosed(iter);
+ }
+ Test1(instantiate(g));
+
+ function Test2(iter) {
+ assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test2(instantiate(g));
+
+ function Test3(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(4, false, iter.throw(new Sentinel));
+ assertThrows(function() { iter.next(); }, Sentinel);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test3(instantiate(g));
+
+ function Test4(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(4, false, iter.throw(new Sentinel));
+ assertThrows(function() { iter.throw(new Sentinel2); }, Sentinel2);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test4(instantiate(g));
+
+ function Test5(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ var exn = new Sentinel;
+ assertIteratorResult(exn, false, iter.throw(exn));
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorResult(4, false, iter.next());
+ assertIteratorResult(5, false, iter.next());
+ assertIteratorIsClosed(iter);
+ }
+ Test5(instantiate(g));
+
+ function Test6(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ var exn = new Sentinel;
+ assertIteratorResult(exn, false, iter.throw(exn));
+ assertIteratorResult(4, false, iter.throw(new Sentinel2));
+ assertThrows(function() { iter.next(); }, Sentinel2);
+ assertThrownIteratorIsClosed(iter);
+ }
+ Test6(instantiate(g));
+
+ function Test7(iter) {
+ assertIteratorResult(1, false, iter.next());
+ assertIteratorResult(2, false, iter.next());
+ var exn = new Sentinel;
+ assertIteratorResult(exn, false, iter.throw(exn));
+ assertIteratorResult(3, false, iter.next());
+ assertIteratorResult(4, false, iter.throw(new Sentinel2));
+ assertThrows(function() { iter.next(); }, Sentinel2);
+ assertThrownIteratorIsClosed(iter);
+ }
+ 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();
+ }
+ assertThrows(TestNextRecursion, Error);
+ assertThrows(TestSendRecursion, Error);
+ assertThrows(TestThrowRecursion, Error);
+}
+TestRecursion();