1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/ecma_6/Generators/iteration.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,574 @@ 1.4 +// This file was written by Andy Wingo <wingo@igalia.com> and originally 1.5 +// contributed to V8 as generators-objects.js, available here: 1.6 +// 1.7 +// http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/harmony/generators-objects.js 1.8 + 1.9 +// Test aspects of the generator runtime. 1.10 + 1.11 + 1.12 +var GeneratorFunction = (function*(){yield 1;}).constructor; 1.13 + 1.14 + 1.15 +function TestGeneratorResultPrototype() { 1.16 + function* g() { yield 1; } 1.17 + var iter = g(); 1.18 + assertIteratorNext(iter, 1); 1.19 + assertIteratorDone(iter, undefined); 1.20 + assertIteratorDone(iter, undefined); 1.21 +} 1.22 +TestGeneratorResultPrototype(); 1.23 + 1.24 +function TestGenerator(g, expected_values_for_next, 1.25 + send_val, expected_values_for_send) { 1.26 + function testNext(thunk) { 1.27 + var iter = thunk(); 1.28 + for (var i = 0; i < expected_values_for_next.length; i++) { 1.29 + assertIteratorResult(iter.next(), expected_values_for_next[i], 1.30 + i == expected_values_for_next.length - 1); 1.31 + } 1.32 + assertIteratorDone(iter, undefined); 1.33 + } 1.34 + function testSend(thunk) { 1.35 + var iter = thunk(); 1.36 + for (var i = 0; i < expected_values_for_send.length; i++) { 1.37 + assertIteratorResult(i ? iter.next(send_val) : iter.next(), 1.38 + expected_values_for_send[i], 1.39 + i == expected_values_for_send.length - 1); 1.40 + } 1.41 + assertIteratorDone(iter, undefined); 1.42 + } 1.43 + function testThrow(thunk) { 1.44 + for (var i = 0; i < expected_values_for_next.length; i++) { 1.45 + var iter = thunk(); 1.46 + for (var j = 0; j < i; j++) { 1.47 + assertIteratorResult(iter.next(), 1.48 + expected_values_for_next[j], 1.49 + j == expected_values_for_next.length - 1); 1.50 + } 1.51 + var Sentinel = function () {} 1.52 + assertThrowsInstanceOf(function () { iter.throw(new Sentinel); }, Sentinel); 1.53 + assertIteratorDone(iter, undefined); 1.54 + } 1.55 + } 1.56 + 1.57 + testNext(g); 1.58 + testSend(g); 1.59 + testThrow(g); 1.60 + 1.61 + testNext(function*() { return yield* g(); }); 1.62 + testSend(function*() { return yield* g(); }); 1.63 + testThrow(function*() { return yield* g(); }); 1.64 + 1.65 + if (g instanceof GeneratorFunction) { 1.66 + testNext(function() { return new g(); }); 1.67 + testSend(function() { return new g(); }); 1.68 + testThrow(function() { return new g(); }); 1.69 + } 1.70 +} 1.71 + 1.72 +TestGenerator(function* g1() { }, 1.73 + [undefined], 1.74 + "foo", 1.75 + [undefined]); 1.76 + 1.77 +TestGenerator(function* g2() { yield 1; }, 1.78 + [1, undefined], 1.79 + "foo", 1.80 + [1, undefined]); 1.81 + 1.82 +TestGenerator(function* g3() { yield 1; yield 2; }, 1.83 + [1, 2, undefined], 1.84 + "foo", 1.85 + [1, 2, undefined]); 1.86 + 1.87 +TestGenerator(function* g4() { yield 1; yield 2; return 3; }, 1.88 + [1, 2, 3], 1.89 + "foo", 1.90 + [1, 2, 3]); 1.91 + 1.92 +TestGenerator(function* g5() { return 1; }, 1.93 + [1], 1.94 + "foo", 1.95 + [1]); 1.96 + 1.97 +TestGenerator(function* g6() { var x = yield 1; return x; }, 1.98 + [1, undefined], 1.99 + "foo", 1.100 + [1, "foo"]); 1.101 + 1.102 +TestGenerator(function* g7() { var x = yield 1; yield 2; return x; }, 1.103 + [1, 2, undefined], 1.104 + "foo", 1.105 + [1, 2, "foo"]); 1.106 + 1.107 +TestGenerator(function* g8() { for (var x = 0; x < 4; x++) { yield x; } }, 1.108 + [0, 1, 2, 3, undefined], 1.109 + "foo", 1.110 + [0, 1, 2, 3, undefined]); 1.111 + 1.112 +// Generator with arguments. 1.113 +TestGenerator( 1.114 + function g9() { 1.115 + return (function*(a, b, c, d) { 1.116 + yield a; yield b; yield c; yield d; 1.117 + })("fee", "fi", "fo", "fum"); 1.118 + }, 1.119 + ["fee", "fi", "fo", "fum", undefined], 1.120 + "foo", 1.121 + ["fee", "fi", "fo", "fum", undefined]); 1.122 + 1.123 +// Too few arguments. 1.124 +TestGenerator( 1.125 + function g10() { 1.126 + return (function*(a, b, c, d) { 1.127 + yield a; yield b; yield c; yield d; 1.128 + })("fee", "fi"); 1.129 + }, 1.130 + ["fee", "fi", undefined, undefined, undefined], 1.131 + "foo", 1.132 + ["fee", "fi", undefined, undefined, undefined]); 1.133 + 1.134 +// Too many arguments. 1.135 +TestGenerator( 1.136 + function g11() { 1.137 + return (function*(a, b, c, d) { 1.138 + yield a; yield b; yield c; yield d; 1.139 + })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman"); 1.140 + }, 1.141 + ["fee", "fi", "fo", "fum", undefined], 1.142 + "foo", 1.143 + ["fee", "fi", "fo", "fum", undefined]); 1.144 + 1.145 +// The arguments object. 1.146 +TestGenerator( 1.147 + function g12() { 1.148 + return (function*(a, b, c, d) { 1.149 + for (var i = 0; i < arguments.length; i++) { 1.150 + yield arguments[i]; 1.151 + } 1.152 + })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman"); 1.153 + }, 1.154 + ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman", 1.155 + undefined], 1.156 + "foo", 1.157 + ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman", 1.158 + undefined]); 1.159 + 1.160 +// Access to captured free variables. 1.161 +TestGenerator( 1.162 + function g13() { 1.163 + return (function(a, b, c, d) { 1.164 + return (function*() { 1.165 + yield a; yield b; yield c; yield d; 1.166 + })(); 1.167 + })("fee", "fi", "fo", "fum"); 1.168 + }, 1.169 + ["fee", "fi", "fo", "fum", undefined], 1.170 + "foo", 1.171 + ["fee", "fi", "fo", "fum", undefined]); 1.172 + 1.173 +// Abusing the arguments object. 1.174 +TestGenerator( 1.175 + function g14() { 1.176 + return (function*(a, b, c, d) { 1.177 + arguments[0] = "Be he live"; 1.178 + arguments[1] = "or be he dead"; 1.179 + arguments[2] = "I'll grind his bones"; 1.180 + arguments[3] = "to make my bread"; 1.181 + yield a; yield b; yield c; yield d; 1.182 + })("fee", "fi", "fo", "fum"); 1.183 + }, 1.184 + ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread", 1.185 + undefined], 1.186 + "foo", 1.187 + ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread", 1.188 + undefined]); 1.189 + 1.190 +// Abusing the arguments object: strict mode. 1.191 +TestGenerator( 1.192 + function g15() { 1.193 + return (function*(a, b, c, d) { 1.194 + "use strict"; 1.195 + arguments[0] = "Be he live"; 1.196 + arguments[1] = "or be he dead"; 1.197 + arguments[2] = "I'll grind his bones"; 1.198 + arguments[3] = "to make my bread"; 1.199 + yield a; yield b; yield c; yield d; 1.200 + })("fee", "fi", "fo", "fum"); 1.201 + }, 1.202 + ["fee", "fi", "fo", "fum", undefined], 1.203 + "foo", 1.204 + ["fee", "fi", "fo", "fum", undefined]); 1.205 + 1.206 +// GC. 1.207 +if (typeof gc == 'function') { 1.208 + TestGenerator(function* g16() { yield "baz"; gc(); yield "qux"; }, 1.209 + ["baz", "qux", undefined], 1.210 + "foo", 1.211 + ["baz", "qux", undefined]); 1.212 +} 1.213 + 1.214 +// Receivers. 1.215 +TestGenerator( 1.216 + function g17() { 1.217 + function* g() { yield this.x; yield this.y; } 1.218 + var o = { start: g, x: 1, y: 2 }; 1.219 + return o.start(); 1.220 + }, 1.221 + [1, 2, undefined], 1.222 + "foo", 1.223 + [1, 2, undefined]); 1.224 + 1.225 +// FIXME: Capture the generator object as "this" in new g(). Bug 907742. 1.226 +// TestGenerator( 1.227 +// function g18() { 1.228 +// function* g() { yield this.x; yield this.y; } 1.229 +// var iter = new g; 1.230 +// iter.x = 1; 1.231 +// iter.y = 2; 1.232 +// return iter; 1.233 +// }, 1.234 +// [1, 2, undefined], 1.235 +// "foo", 1.236 +// [1, 2, undefined]); 1.237 + 1.238 +TestGenerator( 1.239 + function* g19() { 1.240 + var x = 1; 1.241 + yield x; 1.242 + with({x:2}) { yield x; } 1.243 + yield x; 1.244 + }, 1.245 + [1, 2, 1, undefined], 1.246 + "foo", 1.247 + [1, 2, 1, undefined]); 1.248 + 1.249 +TestGenerator( 1.250 + function* g20() { yield (1 + (yield 2) + 3); }, 1.251 + [2, NaN, undefined], 1.252 + "foo", 1.253 + [2, "1foo3", undefined]); 1.254 + 1.255 +TestGenerator( 1.256 + function* g21() { return (1 + (yield 2) + 3); }, 1.257 + [2, NaN], 1.258 + "foo", 1.259 + [2, "1foo3"]); 1.260 + 1.261 +TestGenerator( 1.262 + function* g22() { yield (1 + (yield 2) + 3); yield (4 + (yield 5) + 6); }, 1.263 + [2, NaN, 5, NaN, undefined], 1.264 + "foo", 1.265 + [2, "1foo3", 5, "4foo6", undefined]); 1.266 + 1.267 +TestGenerator( 1.268 + function* g23() { 1.269 + return (yield (1 + (yield 2) + 3)) + (yield (4 + (yield 5) + 6)); 1.270 + }, 1.271 + [2, NaN, 5, NaN, NaN], 1.272 + "foo", 1.273 + [2, "1foo3", 5, "4foo6", "foofoo"]); 1.274 + 1.275 +// Rewind a try context with and without operands on the stack. 1.276 +TestGenerator( 1.277 + function* g24() { 1.278 + try { 1.279 + return (yield (1 + (yield 2) + 3)) + (yield (4 + (yield 5) + 6)); 1.280 + } catch (e) { 1.281 + throw e; 1.282 + } 1.283 + }, 1.284 + [2, NaN, 5, NaN, NaN], 1.285 + "foo", 1.286 + [2, "1foo3", 5, "4foo6", "foofoo"]); 1.287 + 1.288 +// Yielding in a catch context, with and without operands on the stack. 1.289 +TestGenerator( 1.290 + function* g25() { 1.291 + try { 1.292 + throw (yield (1 + (yield 2) + 3)) 1.293 + } catch (e) { 1.294 + if (typeof e == 'object') throw e; 1.295 + return e + (yield (4 + (yield 5) + 6)); 1.296 + } 1.297 + }, 1.298 + [2, NaN, 5, NaN, NaN], 1.299 + "foo", 1.300 + [2, "1foo3", 5, "4foo6", "foofoo"]); 1.301 + 1.302 +// Generator function instances. 1.303 +TestGenerator(GeneratorFunction(), 1.304 + [undefined], 1.305 + "foo", 1.306 + [undefined]); 1.307 + 1.308 +TestGenerator(new GeneratorFunction(), 1.309 + [undefined], 1.310 + "foo", 1.311 + [undefined]); 1.312 + 1.313 +TestGenerator(GeneratorFunction('yield 1;'), 1.314 + [1, undefined], 1.315 + "foo", 1.316 + [1, undefined]); 1.317 + 1.318 +TestGenerator( 1.319 + function() { return GeneratorFunction('x', 'y', 'yield x + y;')(1, 2) }, 1.320 + [3, undefined], 1.321 + "foo", 1.322 + [3, undefined]); 1.323 + 1.324 +// Access to this with formal arguments. 1.325 +TestGenerator( 1.326 + function () { 1.327 + return ({ x: 42, g: function* (a) { yield this.x } }).g(0); 1.328 + }, 1.329 + [42, undefined], 1.330 + "foo", 1.331 + [42, undefined]); 1.332 + 1.333 +function TestTryCatch(instantiate) { 1.334 + function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; } 1.335 + function Sentinel() {} 1.336 + 1.337 + function Test1(iter) { 1.338 + assertIteratorNext(iter, 1); 1.339 + assertIteratorNext(iter, 2); 1.340 + assertIteratorNext(iter, 3); 1.341 + assertIteratorDone(iter, undefined); 1.342 + assertIteratorDone(iter, undefined); 1.343 + } 1.344 + Test1(instantiate(g)); 1.345 + 1.346 + function Test2(iter) { 1.347 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.348 + assertIteratorDone(iter, undefined); 1.349 + } 1.350 + Test2(instantiate(g)); 1.351 + 1.352 + function Test3(iter) { 1.353 + assertIteratorNext(iter, 1); 1.354 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.355 + assertIteratorDone(iter, undefined); 1.356 + } 1.357 + Test3(instantiate(g)); 1.358 + 1.359 + function Test4(iter) { 1.360 + assertIteratorNext(iter, 1); 1.361 + assertIteratorNext(iter, 2); 1.362 + var exn = new Sentinel; 1.363 + assertIteratorResult(iter.throw(exn), exn, false); 1.364 + assertIteratorNext(iter, 3); 1.365 + assertIteratorDone(iter, undefined); 1.366 + assertIteratorDone(iter, undefined); 1.367 + } 1.368 + Test4(instantiate(g)); 1.369 + 1.370 + function Test5(iter) { 1.371 + assertIteratorNext(iter, 1); 1.372 + assertIteratorNext(iter, 2); 1.373 + var exn = new Sentinel; 1.374 + assertIteratorResult(iter.throw(exn), exn, false); 1.375 + assertIteratorNext(iter, 3); 1.376 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.377 + assertIteratorDone(iter, undefined); 1.378 + 1.379 + } 1.380 + Test5(instantiate(g)); 1.381 + 1.382 + function Test6(iter) { 1.383 + assertIteratorNext(iter, 1); 1.384 + assertIteratorNext(iter, 2); 1.385 + var exn = new Sentinel; 1.386 + assertIteratorResult(iter.throw(exn), exn, false); 1.387 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.388 + assertIteratorDone(iter, undefined); 1.389 + } 1.390 + Test6(instantiate(g)); 1.391 +} 1.392 +TestTryCatch(function (g) { return g(); }); 1.393 +TestTryCatch(function* (g) { return yield* g(); }); 1.394 + 1.395 +function TestTryFinally(instantiate) { 1.396 + function* g() { yield 1; try { yield 2; } finally { yield 3; } yield 4; } 1.397 + function Sentinel() {} 1.398 + function Sentinel2() {} 1.399 + 1.400 + function Test1(iter) { 1.401 + assertIteratorNext(iter, 1); 1.402 + assertIteratorNext(iter, 2); 1.403 + assertIteratorNext(iter, 3); 1.404 + assertIteratorNext(iter, 4); 1.405 + assertIteratorDone(iter, undefined); 1.406 + assertIteratorDone(iter, undefined); 1.407 + } 1.408 + Test1(instantiate(g)); 1.409 + 1.410 + function Test2(iter) { 1.411 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.412 + assertIteratorDone(iter, undefined); 1.413 + } 1.414 + Test2(instantiate(g)); 1.415 + 1.416 + function Test3(iter) { 1.417 + assertIteratorNext(iter, 1); 1.418 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.419 + assertIteratorDone(iter, undefined); 1.420 + } 1.421 + Test3(instantiate(g)); 1.422 + 1.423 + function Test4(iter) { 1.424 + assertIteratorNext(iter, 1); 1.425 + assertIteratorNext(iter, 2); 1.426 + assertIteratorResult(iter.throw(new Sentinel), 3, false); 1.427 + assertThrowsInstanceOf(function() { iter.next(); }, Sentinel); 1.428 + assertIteratorDone(iter, undefined); 1.429 + 1.430 + } 1.431 + Test4(instantiate(g)); 1.432 + 1.433 + function Test5(iter) { 1.434 + assertIteratorNext(iter, 1); 1.435 + assertIteratorNext(iter, 2); 1.436 + assertIteratorResult(iter.throw(new Sentinel), 3, false); 1.437 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel2); }, Sentinel2); 1.438 + assertIteratorDone(iter, undefined); 1.439 + } 1.440 + Test5(instantiate(g)); 1.441 + 1.442 + function Test6(iter) { 1.443 + assertIteratorNext(iter, 1); 1.444 + assertIteratorNext(iter, 2); 1.445 + assertIteratorNext(iter, 3); 1.446 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.447 + assertIteratorDone(iter, undefined); 1.448 + } 1.449 + Test6(instantiate(g)); 1.450 + 1.451 + function Test7(iter) { 1.452 + assertIteratorNext(iter, 1); 1.453 + assertIteratorNext(iter, 2); 1.454 + assertIteratorNext(iter, 3); 1.455 + assertIteratorNext(iter, 4); 1.456 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.457 + assertIteratorDone(iter, undefined); 1.458 + } 1.459 + Test7(instantiate(g)); 1.460 +} 1.461 +TestTryFinally(function (g) { return g(); }); 1.462 +TestTryFinally(function* (g) { return yield* g(); }); 1.463 + 1.464 +function TestNestedTry(instantiate) { 1.465 + function* g() { 1.466 + try { 1.467 + yield 1; 1.468 + try { yield 2; } catch (e) { yield e; } 1.469 + yield 3; 1.470 + } finally { 1.471 + yield 4; 1.472 + } 1.473 + yield 5; 1.474 + } 1.475 + function Sentinel() {} 1.476 + function Sentinel2() {} 1.477 + 1.478 + function Test1(iter) { 1.479 + assertIteratorNext(iter, 1); 1.480 + assertIteratorNext(iter, 2); 1.481 + assertIteratorNext(iter, 3); 1.482 + assertIteratorNext(iter, 4); 1.483 + assertIteratorNext(iter, 5); 1.484 + assertIteratorDone(iter, undefined); 1.485 + assertIteratorDone(iter, undefined); 1.486 + } 1.487 + Test1(instantiate(g)); 1.488 + 1.489 + function Test2(iter) { 1.490 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel); }, Sentinel); 1.491 + assertIteratorDone(iter, undefined); 1.492 + } 1.493 + Test2(instantiate(g)); 1.494 + 1.495 + function Test3(iter) { 1.496 + assertIteratorNext(iter, 1); 1.497 + assertIteratorResult(iter.throw(new Sentinel), 4, false); 1.498 + assertThrowsInstanceOf(function() { iter.next(); }, Sentinel); 1.499 + assertIteratorDone(iter, undefined); 1.500 + } 1.501 + Test3(instantiate(g)); 1.502 + 1.503 + function Test4(iter) { 1.504 + assertIteratorNext(iter, 1); 1.505 + assertIteratorResult(iter.throw(new Sentinel), 4, false); 1.506 + assertThrowsInstanceOf(function() { iter.throw(new Sentinel2); }, Sentinel2); 1.507 + assertIteratorDone(iter, undefined); 1.508 + } 1.509 + Test4(instantiate(g)); 1.510 + 1.511 + function Test5(iter) { 1.512 + assertIteratorNext(iter, 1); 1.513 + assertIteratorNext(iter, 2); 1.514 + var exn = new Sentinel; 1.515 + assertIteratorResult(iter.throw(exn), exn, false); 1.516 + assertIteratorNext(iter, 3); 1.517 + assertIteratorNext(iter, 4); 1.518 + assertIteratorNext(iter, 5); 1.519 + assertIteratorDone(iter, undefined); 1.520 + assertIteratorDone(iter, undefined); 1.521 + 1.522 + } 1.523 + Test5(instantiate(g)); 1.524 + 1.525 + function Test6(iter) { 1.526 + assertIteratorNext(iter, 1); 1.527 + assertIteratorNext(iter, 2); 1.528 + var exn = new Sentinel; 1.529 + assertIteratorResult(iter.throw(exn), exn, false); 1.530 + assertIteratorResult(iter.throw(new Sentinel2), 4, false); 1.531 + assertThrowsInstanceOf(function() { iter.next(); }, Sentinel2); 1.532 + assertIteratorDone(iter, undefined); 1.533 + } 1.534 + Test6(instantiate(g)); 1.535 + 1.536 + function Test7(iter) { 1.537 + assertIteratorNext(iter, 1); 1.538 + assertIteratorNext(iter, 2); 1.539 + var exn = new Sentinel; 1.540 + assertIteratorResult(iter.throw(exn), exn, false); 1.541 + assertIteratorNext(iter, 3); 1.542 + assertIteratorResult(iter.throw(new Sentinel2), 4, false); 1.543 + assertThrowsInstanceOf(function() { iter.next(); }, Sentinel2); 1.544 + assertIteratorDone(iter, undefined); 1.545 + 1.546 + } 1.547 + Test7(instantiate(g)); 1.548 + 1.549 + // That's probably enough. 1.550 +} 1.551 +TestNestedTry(function (g) { return g(); }); 1.552 +TestNestedTry(function* (g) { return yield* g(); }); 1.553 + 1.554 +function TestRecursion() { 1.555 + function TestNextRecursion() { 1.556 + function* g() { yield iter.next(); } 1.557 + var iter = g(); 1.558 + return iter.next(); 1.559 + } 1.560 + function TestSendRecursion() { 1.561 + function* g() { yield iter.next(42); } 1.562 + var iter = g(); 1.563 + return iter.next(); 1.564 + } 1.565 + function TestThrowRecursion() { 1.566 + function* g() { yield iter.throw(1); } 1.567 + var iter = g(); 1.568 + return iter.next(); 1.569 + } 1.570 + assertThrowsInstanceOf(TestNextRecursion, TypeError); 1.571 + assertThrowsInstanceOf(TestSendRecursion, TypeError); 1.572 + assertThrowsInstanceOf(TestThrowRecursion, TypeError); 1.573 +} 1.574 +TestRecursion(); 1.575 + 1.576 +if (typeof reportCompare == "function") 1.577 + reportCompare(true, true);