Home | History | Annotate | Download | only in es6
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 // Flags: --expose-gc
     29 
     30 // Test generator iteration.
     31 
     32 var GeneratorFunction = (function*(){yield 1;}).__proto__.constructor;
     33 
     34 function assertIteratorResult(value, done, result) {
     35   assertEquals({ value: value, done: done}, result);
     36 }
     37 
     38 function assertIteratorIsClosed(iter) {
     39   assertIteratorResult(undefined, true, iter.next());
     40   assertDoesNotThrow(function() { iter.next(); });
     41 }
     42 
     43 function assertThrownIteratorIsClosed(iter) {
     44   // TODO(yusukesuzuki): Since status of a thrown generator is "executing",
     45   // following tests are failed.
     46   // https://code.google.com/p/v8/issues/detail?id=3096
     47   // assertIteratorIsClosed(iter);
     48 }
     49 
     50 function TestGeneratorResultPrototype() {
     51   function* g() { yield 1; }
     52   var iter = g();
     53   var result = iter.next();
     54 
     55   assertSame(Object.prototype, Object.getPrototypeOf(result));
     56   property_names = Object.getOwnPropertyNames(result);
     57   property_names.sort();
     58   assertEquals(["done", "value"], property_names);
     59   assertIteratorResult(1, false, result);
     60 }
     61 TestGeneratorResultPrototype()
     62 
     63 function TestGenerator(g, expected_values_for_next,
     64                        send_val, expected_values_for_send) {
     65   function testNext(thunk) {
     66     var iter = thunk();
     67     for (var i = 0; i < expected_values_for_next.length; i++) {
     68       var v1 = expected_values_for_next[i];
     69       var v2 = i == expected_values_for_next.length - 1;
     70       // var v3 = iter.next();
     71       assertIteratorResult(v1, v2, iter.next());
     72     }
     73     assertIteratorIsClosed(iter);
     74   }
     75   function testSend(thunk) {
     76     var iter = thunk();
     77     for (var i = 0; i < expected_values_for_send.length; i++) {
     78       assertIteratorResult(expected_values_for_send[i],
     79                            i == expected_values_for_send.length - 1,
     80                            iter.next(send_val));
     81     }
     82     assertIteratorIsClosed(iter);
     83   }
     84   function testThrow(thunk) {
     85     for (var i = 0; i < expected_values_for_next.length; i++) {
     86       var iter = thunk();
     87       for (var j = 0; j < i; j++) {
     88         assertIteratorResult(expected_values_for_next[j],
     89                              j == expected_values_for_next.length - 1,
     90                              iter.next());
     91       }
     92       function Sentinel() {}
     93       assertThrows(function () { iter.throw(new Sentinel); }, Sentinel);
     94       assertThrownIteratorIsClosed(iter);
     95     }
     96   }
     97 
     98   testNext(g);
     99   testSend(g);
    100   testThrow(g);
    101 
    102   testNext(function*() { return yield* g(); });
    103   testSend(function*() { return yield* g(); });
    104   testThrow(function*() { return yield* g(); });
    105 
    106   if (g instanceof GeneratorFunction) {
    107     testNext(function() { return new g(); });
    108     testSend(function() { return new g(); });
    109     testThrow(function() { return new g(); });
    110   }
    111 }
    112 
    113 TestGenerator(function* g1() { },
    114               [undefined],
    115               "foo",
    116               [undefined]);
    117 
    118 TestGenerator(function* g2() { yield 1; },
    119               [1, undefined],
    120               "foo",
    121               [1, undefined]);
    122 
    123 TestGenerator(function* g3() { yield 1; yield 2; },
    124               [1, 2, undefined],
    125               "foo",
    126               [1, 2, undefined]);
    127 
    128 TestGenerator(function* g4() { yield 1; yield 2; return 3; },
    129               [1, 2, 3],
    130               "foo",
    131               [1, 2, 3]);
    132 
    133 TestGenerator(function* g5() { return 1; },
    134               [1],
    135              "foo",
    136               [1]);
    137 
    138 TestGenerator(function* g6() { var x = yield 1; return x; },
    139               [1, undefined],
    140               "foo",
    141               [1, "foo"]);
    142 
    143 TestGenerator(function* g7() { var x = yield 1; yield 2; return x; },
    144               [1, 2, undefined],
    145               "foo",
    146               [1, 2, "foo"]);
    147 
    148 TestGenerator(function* g8() { for (var x = 0; x < 4; x++) { yield x; } },
    149               [0, 1, 2, 3, undefined],
    150               "foo",
    151               [0, 1, 2, 3, undefined]);
    152 
    153 // Generator with arguments.
    154 TestGenerator(
    155     function g9() {
    156       return (function*(a, b, c, d) {
    157         yield a; yield b; yield c; yield d;
    158       })("fee", "fi", "fo", "fum");
    159     },
    160     ["fee", "fi", "fo", "fum", undefined],
    161     "foo",
    162     ["fee", "fi", "fo", "fum", undefined]);
    163 
    164 // Too few arguments.
    165 TestGenerator(
    166     function g10() {
    167       return (function*(a, b, c, d) {
    168         yield a; yield b; yield c; yield d;
    169       })("fee", "fi");
    170     },
    171     ["fee", "fi", undefined, undefined, undefined],
    172     "foo",
    173     ["fee", "fi", undefined, undefined, undefined]);
    174 
    175 // Too many arguments.
    176 TestGenerator(
    177     function g11() {
    178       return (function*(a, b, c, d) {
    179         yield a; yield b; yield c; yield d;
    180       })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman");
    181     },
    182     ["fee", "fi", "fo", "fum", undefined],
    183     "foo",
    184     ["fee", "fi", "fo", "fum", undefined]);
    185 
    186 // The arguments object.
    187 TestGenerator(
    188     function g12() {
    189       return (function*(a, b, c, d) {
    190         for (var i = 0; i < arguments.length; i++) {
    191           yield arguments[i];
    192         }
    193       })("fee", "fi", "fo", "fum", "I smell the blood of an Englishman");
    194     },
    195     ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman",
    196      undefined],
    197     "foo",
    198     ["fee", "fi", "fo", "fum", "I smell the blood of an Englishman",
    199      undefined]);
    200 
    201 // Access to captured free variables.
    202 TestGenerator(
    203     function g13() {
    204       return (function(a, b, c, d) {
    205         return (function*() {
    206           yield a; yield b; yield c; yield d;
    207         })();
    208       })("fee", "fi", "fo", "fum");
    209     },
    210     ["fee", "fi", "fo", "fum", undefined],
    211     "foo",
    212     ["fee", "fi", "fo", "fum", undefined]);
    213 
    214 // Abusing the arguments object.
    215 TestGenerator(
    216     function g14() {
    217       return (function*(a, b, c, d) {
    218         arguments[0] = "Be he live";
    219         arguments[1] = "or be he dead";
    220         arguments[2] = "I'll grind his bones";
    221         arguments[3] = "to make my bread";
    222         yield a; yield b; yield c; yield d;
    223       })("fee", "fi", "fo", "fum");
    224     },
    225     ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread",
    226      undefined],
    227     "foo",
    228     ["Be he live", "or be he dead", "I'll grind his bones", "to make my bread",
    229      undefined]);
    230 
    231 // Abusing the arguments object: strict mode.
    232 TestGenerator(
    233     function g15() {
    234       return (function*(a, b, c, d) {
    235         "use strict";
    236         arguments[0] = "Be he live";
    237         arguments[1] = "or be he dead";
    238         arguments[2] = "I'll grind his bones";
    239         arguments[3] = "to make my bread";
    240         yield a; yield b; yield c; yield d;
    241       })("fee", "fi", "fo", "fum");
    242     },
    243     ["fee", "fi", "fo", "fum", undefined],
    244     "foo",
    245     ["fee", "fi", "fo", "fum", undefined]);
    246 
    247 // GC.
    248 TestGenerator(function* g16() { yield "baz"; gc(); yield "qux"; },
    249               ["baz", "qux", undefined],
    250               "foo",
    251               ["baz", "qux", undefined]);
    252 
    253 // Receivers.
    254 TestGenerator(
    255     function g17() {
    256       function* g() { yield this.x; yield this.y; }
    257       var o = { start: g, x: 1, y: 2 };
    258       return o.start();
    259     },
    260     [1, 2, undefined],
    261     "foo",
    262     [1, 2, undefined]);
    263 
    264 TestGenerator(
    265     function g18() {
    266       function* g() { yield this.x; yield this.y; }
    267       var iter = new g;
    268       iter.x = 1;
    269       iter.y = 2;
    270       return iter;
    271     },
    272     [1, 2, undefined],
    273     "foo",
    274     [1, 2, undefined]);
    275 
    276 TestGenerator(
    277     function* g19() {
    278       var x = 1;
    279       yield x;
    280       with({x:2}) { yield x; }
    281       yield x;
    282     },
    283     [1, 2, 1, undefined],
    284     "foo",
    285     [1, 2, 1, undefined]);
    286 
    287 TestGenerator(
    288     function* g20() { yield (1 + (yield 2) + 3); },
    289     [2, NaN, undefined],
    290     "foo",
    291     [2, "1foo3", undefined]);
    292 
    293 TestGenerator(
    294     function* g21() { return (1 + (yield 2) + 3); },
    295     [2, NaN],
    296     "foo",
    297     [2, "1foo3"]);
    298 
    299 TestGenerator(
    300     function* g22() { yield (1 + (yield 2) + 3); yield (4 + (yield 5) + 6); },
    301     [2, NaN, 5, NaN, undefined],
    302     "foo",
    303     [2, "1foo3", 5, "4foo6", undefined]);
    304 
    305 TestGenerator(
    306     function* g23() {
    307       return (yield (1 + (yield 2) + 3)) + (yield (4 + (yield 5) + 6));
    308     },
    309     [2, NaN, 5, NaN, NaN],
    310     "foo",
    311     [2, "1foo3", 5, "4foo6", "foofoo"]);
    312 
    313 // Rewind a try context with and without operands on the stack.
    314 TestGenerator(
    315     function* g24() {
    316       try {
    317         return (yield (1 + (yield 2) + 3)) + (yield (4 + (yield 5) + 6));
    318       } catch (e) {
    319         throw e;
    320       }
    321     },
    322     [2, NaN, 5, NaN, NaN],
    323     "foo",
    324     [2, "1foo3", 5, "4foo6", "foofoo"]);
    325 
    326 // Yielding in a catch context, with and without operands on the stack.
    327 TestGenerator(
    328     function* g25() {
    329       try {
    330         throw (yield (1 + (yield 2) + 3))
    331       } catch (e) {
    332         if (typeof e == 'object') throw e;
    333         return e + (yield (4 + (yield 5) + 6));
    334       }
    335     },
    336     [2, NaN, 5, NaN, NaN],
    337     "foo",
    338     [2, "1foo3", 5, "4foo6", "foofoo"]);
    339 
    340 // Yield with no arguments yields undefined.
    341 TestGenerator(
    342     function* g26() { return yield yield },
    343     [undefined, undefined, undefined],
    344     "foo",
    345     [undefined, "foo", "foo"]);
    346 
    347 // A newline causes the parser to stop looking for an argument to yield.
    348 TestGenerator(
    349     function* g27() {
    350       yield
    351       3
    352       return
    353     },
    354     [undefined, undefined],
    355     "foo",
    356     [undefined, undefined]);
    357 
    358 // TODO(wingo): We should use TestGenerator for these, except that
    359 // currently yield* will unconditionally propagate a throw() to the
    360 // delegate iterator, which fails for these iterators that don't have
    361 // throw().  See http://code.google.com/p/v8/issues/detail?id=3484.
    362 (function() {
    363     function* g28() {
    364       yield* [1, 2, 3];
    365     }
    366     var iter = g28();
    367     assertIteratorResult(1, false, iter.next());
    368     assertIteratorResult(2, false, iter.next());
    369     assertIteratorResult(3, false, iter.next());
    370     assertIteratorResult(undefined, true, iter.next());
    371 })();
    372 
    373 (function() {
    374     function* g29() {
    375       yield* "abc";
    376     }
    377     var iter = g29();
    378     assertIteratorResult("a", false, iter.next());
    379     assertIteratorResult("b", false, iter.next());
    380     assertIteratorResult("c", false, iter.next());
    381     assertIteratorResult(undefined, true, iter.next());
    382 })();
    383 
    384 // Generator function instances.
    385 TestGenerator(GeneratorFunction(),
    386               [undefined],
    387               "foo",
    388               [undefined]);
    389 
    390 TestGenerator(new GeneratorFunction(),
    391               [undefined],
    392               "foo",
    393               [undefined]);
    394 
    395 TestGenerator(GeneratorFunction('yield 1;'),
    396               [1, undefined],
    397               "foo",
    398               [1, undefined]);
    399 
    400 TestGenerator(
    401     function() { return GeneratorFunction('x', 'y', 'yield x + y;')(1, 2) },
    402     [3, undefined],
    403     "foo",
    404     [3, undefined]);
    405 
    406 // Access to this with formal arguments.
    407 TestGenerator(
    408     function () {
    409       return ({ x: 42, g: function* (a) { yield this.x } }).g(0);
    410     },
    411     [42, undefined],
    412     "foo",
    413     [42, undefined]);
    414 
    415 // Test that yield* re-yields received results without re-boxing.
    416 function TestDelegatingYield() {
    417   function results(results) {
    418     var i = 0;
    419     function next() {
    420       return results[i++];
    421     }
    422     var iter = { next: next };
    423     var ret = {};
    424     ret[Symbol.iterator] = function() { return iter; };
    425     return ret;
    426   }
    427   function* yield_results(expected) {
    428     return yield* results(expected);
    429   }
    430   function collect_results(iterable) {
    431     var iter = iterable[Symbol.iterator]();
    432     var ret = [];
    433     var result;
    434     do {
    435       result = iter.next();
    436       ret.push(result);
    437     } while (!result.done);
    438     return ret;
    439   }
    440   // We have to put a full result for the end, because the return will re-box.
    441   var expected = [{value: 1}, 13, "foo", {value: 34, done: true}];
    442 
    443   // Sanity check.
    444   assertEquals(expected, collect_results(results(expected)));
    445   assertEquals(expected, collect_results(yield_results(expected)));
    446 }
    447 TestDelegatingYield();
    448 
    449 function TestTryCatch(instantiate) {
    450   function* g() { yield 1; try { yield 2; } catch (e) { yield e; } yield 3; }
    451   function Sentinel() {}
    452 
    453   function Test1(iter) {
    454     assertIteratorResult(1, false, iter.next());
    455     assertIteratorResult(2, false, iter.next());
    456     assertIteratorResult(3, false, iter.next());
    457     assertIteratorIsClosed(iter);
    458   }
    459   Test1(instantiate(g));
    460 
    461   function Test2(iter) {
    462     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    463     assertThrownIteratorIsClosed(iter);
    464   }
    465   Test2(instantiate(g));
    466 
    467   function Test3(iter) {
    468     assertIteratorResult(1, false, iter.next());
    469     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    470     assertThrownIteratorIsClosed(iter);
    471   }
    472   Test3(instantiate(g));
    473 
    474   function Test4(iter) {
    475     assertIteratorResult(1, false, iter.next());
    476     assertIteratorResult(2, false, iter.next());
    477     var exn = new Sentinel;
    478     assertIteratorResult(exn, false, iter.throw(exn));
    479     assertIteratorResult(3, false, iter.next());
    480     assertIteratorIsClosed(iter);
    481   }
    482   Test4(instantiate(g));
    483 
    484   function Test5(iter) {
    485     assertIteratorResult(1, false, iter.next());
    486     assertIteratorResult(2, false, iter.next());
    487     var exn = new Sentinel;
    488     assertIteratorResult(exn, false, iter.throw(exn));
    489     assertIteratorResult(3, false, iter.next());
    490     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    491     assertThrownIteratorIsClosed(iter);
    492   }
    493   Test5(instantiate(g));
    494 
    495   function Test6(iter) {
    496     assertIteratorResult(1, false, iter.next());
    497     assertIteratorResult(2, false, iter.next());
    498     var exn = new Sentinel;
    499     assertIteratorResult(exn, false, iter.throw(exn));
    500     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    501     assertThrownIteratorIsClosed(iter);
    502   }
    503   Test6(instantiate(g));
    504 
    505   function Test7(iter) {
    506     assertIteratorResult(1, false, iter.next());
    507     assertIteratorResult(2, false, iter.next());
    508     assertIteratorResult(3, false, iter.next());
    509     assertIteratorIsClosed(iter);
    510   }
    511   Test7(instantiate(g));
    512 }
    513 TestTryCatch(function (g) { return g(); });
    514 TestTryCatch(function* (g) { return yield* g(); });
    515 
    516 function TestTryFinally(instantiate) {
    517   function* g() { yield 1; try { yield 2; } finally { yield 3; } yield 4; }
    518   function Sentinel() {}
    519   function Sentinel2() {}
    520 
    521   function Test1(iter) {
    522     assertIteratorResult(1, false, iter.next());
    523     assertIteratorResult(2, false, iter.next());
    524     assertIteratorResult(3, false, iter.next());
    525     assertIteratorResult(4, false, iter.next());
    526     assertIteratorIsClosed(iter);
    527   }
    528   Test1(instantiate(g));
    529 
    530   function Test2(iter) {
    531     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    532     assertThrownIteratorIsClosed(iter);
    533   }
    534   Test2(instantiate(g));
    535 
    536   function Test3(iter) {
    537     assertIteratorResult(1, false, iter.next());
    538     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    539     assertThrownIteratorIsClosed(iter);
    540   }
    541   Test3(instantiate(g));
    542 
    543   function Test4(iter) {
    544     assertIteratorResult(1, false, iter.next());
    545     assertIteratorResult(2, false, iter.next());
    546     assertIteratorResult(3, false, iter.throw(new Sentinel));
    547     assertThrows(function() { iter.next(); }, Sentinel);
    548     assertThrownIteratorIsClosed(iter);
    549   }
    550   Test4(instantiate(g));
    551 
    552   function Test5(iter) {
    553     assertIteratorResult(1, false, iter.next());
    554     assertIteratorResult(2, false, iter.next());
    555     assertIteratorResult(3, false, iter.throw(new Sentinel));
    556     assertThrows(function() { iter.throw(new Sentinel2); }, Sentinel2);
    557     assertThrownIteratorIsClosed(iter);
    558   }
    559   Test5(instantiate(g));
    560 
    561   function Test6(iter) {
    562     assertIteratorResult(1, false, iter.next());
    563     assertIteratorResult(2, false, iter.next());
    564     assertIteratorResult(3, false, iter.next());
    565     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    566     assertThrownIteratorIsClosed(iter);
    567   }
    568   Test6(instantiate(g));
    569 
    570   function Test7(iter) {
    571     assertIteratorResult(1, false, iter.next());
    572     assertIteratorResult(2, false, iter.next());
    573     assertIteratorResult(3, false, iter.next());
    574     assertIteratorResult(4, false, iter.next());
    575     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    576     assertThrownIteratorIsClosed(iter);
    577   }
    578   Test7(instantiate(g));
    579 
    580   function Test8(iter) {
    581     assertIteratorResult(1, false, iter.next());
    582     assertIteratorResult(2, false, iter.next());
    583     assertIteratorResult(3, false, iter.next());
    584     assertIteratorResult(4, false, iter.next());
    585     assertIteratorIsClosed(iter);
    586   }
    587   Test8(instantiate(g));
    588 }
    589 TestTryFinally(function (g) { return g(); });
    590 TestTryFinally(function* (g) { return yield* g(); });
    591 
    592 function TestNestedTry(instantiate) {
    593   function* g() {
    594     try {
    595       yield 1;
    596       try { yield 2; } catch (e) { yield e; }
    597       yield 3;
    598     } finally {
    599       yield 4;
    600     }
    601     yield 5;
    602   }
    603   function Sentinel() {}
    604   function Sentinel2() {}
    605 
    606   function Test1(iter) {
    607     assertIteratorResult(1, false, iter.next());
    608     assertIteratorResult(2, false, iter.next());
    609     assertIteratorResult(3, false, iter.next());
    610     assertIteratorResult(4, false, iter.next());
    611     assertIteratorResult(5, false, iter.next());
    612     assertIteratorIsClosed(iter);
    613   }
    614   Test1(instantiate(g));
    615 
    616   function Test2(iter) {
    617     assertThrows(function() { iter.throw(new Sentinel); }, Sentinel);
    618     assertThrownIteratorIsClosed(iter);
    619   }
    620   Test2(instantiate(g));
    621 
    622   function Test3(iter) {
    623     assertIteratorResult(1, false, iter.next());
    624     assertIteratorResult(4, false, iter.throw(new Sentinel));
    625     assertThrows(function() { iter.next(); }, Sentinel);
    626     assertThrownIteratorIsClosed(iter);
    627   }
    628   Test3(instantiate(g));
    629 
    630   function Test4(iter) {
    631     assertIteratorResult(1, false, iter.next());
    632     assertIteratorResult(4, false, iter.throw(new Sentinel));
    633     assertThrows(function() { iter.throw(new Sentinel2); }, Sentinel2);
    634     assertThrownIteratorIsClosed(iter);
    635   }
    636   Test4(instantiate(g));
    637 
    638   function Test5(iter) {
    639     assertIteratorResult(1, false, iter.next());
    640     assertIteratorResult(2, false, iter.next());
    641     var exn = new Sentinel;
    642     assertIteratorResult(exn, false, iter.throw(exn));
    643     assertIteratorResult(3, false, iter.next());
    644     assertIteratorResult(4, false, iter.next());
    645     assertIteratorResult(5, false, iter.next());
    646     assertIteratorIsClosed(iter);
    647   }
    648   Test5(instantiate(g));
    649 
    650   function Test6(iter) {
    651     assertIteratorResult(1, false, iter.next());
    652     assertIteratorResult(2, false, iter.next());
    653     var exn = new Sentinel;
    654     assertIteratorResult(exn, false, iter.throw(exn));
    655     assertIteratorResult(4, false, iter.throw(new Sentinel2));
    656     assertThrows(function() { iter.next(); }, Sentinel2);
    657     assertThrownIteratorIsClosed(iter);
    658   }
    659   Test6(instantiate(g));
    660 
    661   function Test7(iter) {
    662     assertIteratorResult(1, false, iter.next());
    663     assertIteratorResult(2, false, iter.next());
    664     var exn = new Sentinel;
    665     assertIteratorResult(exn, false, iter.throw(exn));
    666     assertIteratorResult(3, false, iter.next());
    667     assertIteratorResult(4, false, iter.throw(new Sentinel2));
    668     assertThrows(function() { iter.next(); }, Sentinel2);
    669     assertThrownIteratorIsClosed(iter);
    670   }
    671   Test7(instantiate(g));
    672 
    673   // That's probably enough.
    674 }
    675 TestNestedTry(function (g) { return g(); });
    676 TestNestedTry(function* (g) { return yield* g(); });
    677 
    678 function TestRecursion() {
    679   function TestNextRecursion() {
    680     function* g() { yield iter.next(); }
    681     var iter = g();
    682     return iter.next();
    683   }
    684   function TestSendRecursion() {
    685     function* g() { yield iter.next(42); }
    686     var iter = g();
    687     return iter.next();
    688   }
    689   function TestThrowRecursion() {
    690     function* g() { yield iter.throw(1); }
    691     var iter = g();
    692     return iter.next();
    693   }
    694   assertThrows(TestNextRecursion, Error);
    695   assertThrows(TestSendRecursion, Error);
    696   assertThrows(TestThrowRecursion, Error);
    697 }
    698 TestRecursion();
    699