mirror of
				https://github.com/tc39/test262.git
				synced 2025-11-03 21:24:30 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			675 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			675 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
// 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) {
 | 
						|
  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(g);
 | 
						|
    testSend(g);
 | 
						|
    testThrow(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* 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* validates iterator results.
 | 
						|
function TestDelegatingYield(junk) {
 | 
						|
  var iterator = {next: () => junk};
 | 
						|
  var iterable = {[Symbol.iterator]: () => iterator};
 | 
						|
  function* g() { return yield* iterable };
 | 
						|
  assertThrows(() => g().next(), TypeError);
 | 
						|
}
 | 
						|
TestDelegatingYield();
 | 
						|
TestDelegatingYield(null);
 | 
						|
TestDelegatingYield(42);
 | 
						|
TestDelegatingYield(true);
 | 
						|
 | 
						|
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();
 | 
						|
 | 
						|
 | 
						|
// Test yield* on non-iterable objects.
 | 
						|
function* g(junk) { return yield* junk }
 | 
						|
var non_iterables = [
 | 
						|
  42,
 | 
						|
  {[Symbol.iterator]: 42},
 | 
						|
  {[Symbol.iterator]: () => 42},
 | 
						|
  {[Symbol.iterator]: () => ({next: 42})},
 | 
						|
];
 | 
						|
for (let junk of non_iterables) {
 | 
						|
  assertThrows(() => g(junk).next(), TypeError);
 | 
						|
}
 |