mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-31 03:34:08 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			1383 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1383 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Copyright 2016 the V8 project authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style license that can be
 | |
| // found in the LICENSE file.
 | |
| 
 | |
| 
 | |
| function* g() { yield 42; return 88 };
 | |
| 
 | |
| 
 | |
| // Return method is "undefined".
 | |
| {
 | |
|   g.prototype.return = null;
 | |
| 
 | |
| 
 | |
|   assertEquals(undefined, (() => {
 | |
|     for (var x of g()) { break; }
 | |
|   })());
 | |
| 
 | |
|   assertEquals(undefined, (() => {
 | |
|     for (let x of g()) { break; }
 | |
|   })());
 | |
| 
 | |
|   assertEquals(undefined, (() => {
 | |
|     for (const x of g()) { break; }
 | |
|   })());
 | |
| 
 | |
|   assertEquals(undefined, (() => {
 | |
|     for (x of g()) { break; }
 | |
|   })());
 | |
| 
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) { throw 42; }
 | |
|   }, 42);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) { throw 42; }
 | |
|   }, 42);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) { throw 42; }
 | |
|   }, 42);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) { throw 42; }
 | |
|   }, 42);
 | |
| 
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     for (var x of g()) { return 42; }
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     for (let x of g()) { return 42; }
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     for (const x of g()) { return 42; }
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     for (x of g()) { return 42; }
 | |
|   })());
 | |
| 
 | |
| 
 | |
|   assertEquals(42, eval('for (var x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (let x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (const x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (x of g()) { x; }'));
 | |
| 
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     var [x] = g(); return x;
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     let [x] = g(); return x;
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     const [x] = g(); return x;
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     [x] = g(); return x;
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42,
 | |
|     (([x]) => x)(g())
 | |
|   );
 | |
| }
 | |
| 
 | |
| 
 | |
| // Return method is not callable.
 | |
| {
 | |
|   g.prototype.return = 666;
 | |
| 
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (var x of g()) { break; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (let x of g()) { break; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (const x of g()) { break; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (x of g()) { break; }
 | |
|   }, TypeError);
 | |
| 
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (var x of g()) { throw 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (let x of g()) { throw 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (const x of g()) { throw 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (x of g()) { throw 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (var x of g()) { return 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (let x of g()) { return 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (const x of g()) { return 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (x of g()) { return 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
| 
 | |
|   assertEquals(42, eval('for (var x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (let x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (const x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (x of g()) { x; }'));
 | |
| 
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     var [x] = g(); return x;
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     let [x] = g(); return x;
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     const [x] = g(); return x;
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     [x] = g(); return x;
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     (([x]) => x)(g());
 | |
|   }, TypeError);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Return method does not return an object.
 | |
| {
 | |
|   g.prototype.return = () => 666;
 | |
| 
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (var x of g()) { break; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (let x of g()) { break; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (const x of g()) { break; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (x of g()) { break; }
 | |
|   }, TypeError);
 | |
| 
 | |
| 
 | |
|   // Throw from the body of a for loop 'wins' vs throw
 | |
|   // originating from a bad 'return' value.
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) { throw 666; }
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) { throw 666; }
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) { throw 666; }
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) { throw 666; }
 | |
|   }, 666);
 | |
| 
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (var x of g()) { return 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (let x of g()) { return 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (const x of g()) { return 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     for (x of g()) { return 666; }
 | |
|   }, TypeError);
 | |
| 
 | |
| 
 | |
|   assertEquals(42, eval('for (var x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (let x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (const x of g()) { x; }'));
 | |
| 
 | |
|   assertEquals(42, eval('for (x of g()) { x; }'));
 | |
| 
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     var [x] = g(); return x;
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     let [x] = g(); return x;
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     const [x] = g(); return x;
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     [x] = g(); return x;
 | |
|   }, TypeError);
 | |
| 
 | |
|   assertThrows(() => {
 | |
|     (([x]) => x)(g());
 | |
|   }, TypeError);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Return method returns an object.
 | |
| {
 | |
|   let log = [];
 | |
|   g.prototype.return = (...args) => { log.push(args); return {} };
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   for (var x of g()) { break; }
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   for (let x of g()) { break; }
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   for (const x of g()) { break; }
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   for (x of g()) { break; }
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) { throw 42; }
 | |
|   }, 42);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) { throw 42; }
 | |
|   }, 42);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) { throw 42; }
 | |
|   }, 42);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) { throw 42; }
 | |
|   }, 42);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     for (var x of g()) { return 42; }
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     for (let x of g()) { return 42; }
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     for (const x of g()) { return 42; }
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     for (x of g()) { return 42; }
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, eval('for (var x of g()) { x; }'));
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, eval('for (let x of g()) { x; }'));
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, eval('for (const x of g()) { x; }'));
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, eval('for (x of g()) { x; }'));
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   // Even if doing the assignment throws, still call return
 | |
|   log = [];
 | |
|   x = { set attr(_) { throw 1234; } };
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x.attr of g()) { throw 456; }
 | |
|   }, 1234);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     var [x] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     let [x] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     const [x] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     [x] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals(42,
 | |
|     (([x]) => x)(g())
 | |
|   );
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     var [x,] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     let [x,] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     const [x,] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     [x,] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals(42,
 | |
|     (([x,]) => x)(g())
 | |
|   );
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     var [x,,] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     let [x,,] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     const [x,,] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, (() => {
 | |
|     [x,,] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals(42,
 | |
|     (([x,,]) => x)(g())
 | |
|   );
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, undefined], (() => {
 | |
|     var [x, y] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, undefined], (() => {
 | |
|     let [x, y] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, undefined], (() => {
 | |
|     const [x, y] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, undefined], (() => {
 | |
|     [x, y] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals([42, undefined],
 | |
|     (([x, y]) => [x, y])(g())
 | |
|   );
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42], (() => {
 | |
|     var [...x] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42], (() => {
 | |
|     let [...x] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42], (() => {
 | |
|     const [...x] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42], (() => {
 | |
|     [...x] = g(); return x;
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals([42],
 | |
|     (([...x]) => x)(g())
 | |
|   );
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, []], (() => {
 | |
|     var [x, ...y] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, []], (() => {
 | |
|     let [x, ...y] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, []], (() => {
 | |
|     const [x, ...y] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, []], (() => {
 | |
|     [x, ...y] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals([42, []],
 | |
|     (([x, ...y]) => [x, y])(g())
 | |
|   );
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([], (() => {
 | |
|     var [] = g(); return [];
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([], (() => {
 | |
|     let [] = g(); return [];
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([], (() => {
 | |
|     const [] = g(); return [];
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([], (() => {
 | |
|     [] = g(); return [];
 | |
|   })());
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals([],
 | |
|     (([]) => [])(g())
 | |
|   );
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([], (() => {
 | |
|     var [...[]] = g(); return [];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([], (() => {
 | |
|     let [...[]] = g(); return [];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([], (() => {
 | |
|     const [...[]] = g(); return [];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([], (() => {
 | |
|     [...[]] = g(); return [];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals([],
 | |
|     (([...[]]) => [])(g())
 | |
|   );
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42], (() => {
 | |
|     var [...[x]] = g(); return [x];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42], (() => {
 | |
|     let [...[x]] = g(); return [x];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42], (() => {
 | |
|     const [...[x]] = g(); return [x];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42], (() => {
 | |
|     [...[x]] = g(); return [x];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals([42],
 | |
|     (([...[x]]) => [x])(g())
 | |
|   );
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, undefined], (() => {
 | |
|     var [...[x, y]] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, undefined], (() => {
 | |
|     let [...[x, y]] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, undefined], (() => {
 | |
|     const [...[x, y]] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals([42, undefined], (() => {
 | |
|     [...[x, y]] = g(); return [x, y];
 | |
|   })());
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertEquals([42, undefined],
 | |
|     (([...[x, y]]) => [x, y])(g())
 | |
|   );
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   log = []
 | |
|   assertThrowsEquals(() => {
 | |
|     let x = { set foo(_) { throw 666; } };
 | |
|     [x.foo] = g();
 | |
|   }, 666);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     var [[]] = g();
 | |
|   }, TypeError);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     let [[]] = g();
 | |
|   }, TypeError);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     const [[]] = g();
 | |
|   }, TypeError);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     [[]] = g();
 | |
|   }, TypeError);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     (([[]]) => 0)(g());
 | |
|   }, TypeError);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     var [...[[]]] = g();
 | |
|   }, TypeError);
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     let [...[[]]] = g();
 | |
|   }, TypeError);
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     const [...[[]]] = g();
 | |
|   }, TypeError);
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     [...[[]]] = g();
 | |
|   }, TypeError);
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = []
 | |
|   assertThrows(() => {
 | |
|     (([...[[]]]) => 0)(g());
 | |
|   }, TypeError);
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   {
 | |
|     let backup = Array.prototype[Symbol.iterator];
 | |
|     Array.prototype[Symbol.iterator] = () => g();
 | |
| 
 | |
| 
 | |
|     log = [];
 | |
|     assertDoesNotThrow(() => {
 | |
|       var [x, ...[y]] = [1, 2, 3]
 | |
|     });
 | |
|     assertEquals(log, [[]]);
 | |
| 
 | |
|     log = [];
 | |
|     assertDoesNotThrow(() => {
 | |
|       let [x, ...[y]] = [1, 2, 3];
 | |
|     });
 | |
|     assertEquals(log, [[]]);
 | |
| 
 | |
|     log = [];
 | |
|     assertDoesNotThrow(() => {
 | |
|       const [x, ...[y]] = [1, 2, 3];
 | |
|     });
 | |
|     assertEquals(log, [[]]);
 | |
| 
 | |
|     log = [];
 | |
|     assertDoesNotThrow(() => {
 | |
|       (([x, ...[y]]) => {})([1, 2, 3]);
 | |
|     });
 | |
|     assertEquals(log, [[]]);
 | |
| 
 | |
| 
 | |
|     log = [];
 | |
|     assertThrows(() => {
 | |
|       var [x, ...[[]]] = [1, 2, 3];
 | |
|     }, TypeError);
 | |
|     assertEquals(log, [[]]);
 | |
| 
 | |
|     log = [];
 | |
|     assertThrows(() => {
 | |
|       let [x, ...[[]]] = [1, 2, 3];
 | |
|     }, TypeError);
 | |
|     assertEquals(log, [[]]);
 | |
| 
 | |
|     log = [];
 | |
|     assertThrows(() => {
 | |
|       const [x, ...[[]]] = [1, 2, 3];
 | |
|     }, TypeError);
 | |
|     assertEquals(log, [[]]);
 | |
| 
 | |
|     log = [];
 | |
|     assertThrows(() => {
 | |
|       (([x, ...[[]]]) => {})([1, 2, 3]);
 | |
|     }, TypeError);
 | |
|     assertEquals(log, [[]]);
 | |
| 
 | |
| 
 | |
|     log = [];
 | |
|     assertDoesNotThrow(() => {
 | |
|       var [x, ...[...y]] = [1, 2, 3];
 | |
|     });
 | |
|     assertEquals(log, []);
 | |
| 
 | |
|     log = [];
 | |
|     assertDoesNotThrow(() => {
 | |
|       let [x, ...[...y]] = [1, 2, 3];
 | |
|     });
 | |
|     assertEquals(log, []);
 | |
| 
 | |
|     log = [];
 | |
|     assertDoesNotThrow(() => {
 | |
|       const [x, ...[...y]] = [1, 2, 3];
 | |
|     });
 | |
|     assertEquals(log, []);
 | |
| 
 | |
|     log = [];
 | |
|     assertDoesNotThrow(() => {
 | |
|       (([x, ...[...y]]) => {})([1, 2, 3]);
 | |
|     });
 | |
|     assertEquals(log, []);
 | |
| 
 | |
| 
 | |
|     Array.prototype[Symbol.iterator] = backup;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| // Return method throws.
 | |
| {
 | |
|   let log = [];
 | |
|   g.prototype.return = (...args) => { log.push(args); throw 23 };
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) { break; }
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) { break; }
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) { break; }
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) { break; }
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) { throw 42; }
 | |
|   }, 42);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) { throw 42; }
 | |
|   }, 42);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) { throw 42; }
 | |
|   }, 42);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) { throw 42; }
 | |
|   }, 42);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) { return 42; }
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) { return 42; }
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) { return 42; }
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) { return 42; }
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, eval('for (var x of g()) { x; }'));
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, eval('for (let x of g()) { x; }'));
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, eval('for (const x of g()) { x; }'));
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertEquals(42, eval('for (x of g()) { x; }'));
 | |
|   assertEquals([], log);
 | |
| 
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     var [x] = g(); return x;
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     let [x] = g(); return x;
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     const [x] = g(); return x;
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     [x] = g(); return x;
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     (([x]) => x)(g())
 | |
|   }, 23);
 | |
|   assertEquals([[]], log);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Next method throws.
 | |
| {
 | |
|   let closed = false;
 | |
|   g.prototype.next = () => { throw 666; };
 | |
|   g.prototype.return = () => { closed = true; };
 | |
| 
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     var [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     let [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     const [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     (([x]) => x)(g());
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     var [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     let [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     const [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     (([...x]) => x)(g());
 | |
|   }, 666);
 | |
| 
 | |
| 
 | |
|   assertFalse(closed);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Value throws.
 | |
| {
 | |
|   let closed = false;
 | |
|   g.prototype.next = () => ({get value() {throw 666}});
 | |
|   g.prototype.return = () => { closed = true; };
 | |
| 
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     var [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     let [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     const [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     (([x]) => x)(g());
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     var [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     let [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     const [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     (([...x]) => x)(g());
 | |
|   }, 666);
 | |
| 
 | |
| 
 | |
|   assertFalse(closed);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Done throws.
 | |
| {
 | |
|   let closed = false;
 | |
|   g.prototype.next = () => ({get done() {throw 666}});
 | |
|   g.prototype.return = () => { closed = true; };
 | |
| 
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (var x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (const x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (x of g()) {}
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     var [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     let [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     const [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     [x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     (([x]) => x)(g());
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     var [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     let [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     const [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     [...x] = g();
 | |
|   }, 666);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     (([...x]) => x)(g());
 | |
|   }, 666);
 | |
| 
 | |
| 
 | |
|   assertFalse(closed);
 | |
| }
 | |
| 
 | |
| 
 | |
| // Nested loops.
 | |
| {
 | |
|   function* g1() { yield 1; yield 2; throw 3; }
 | |
|   function* g2() { yield -1; yield -2; throw -3; }
 | |
| 
 | |
|   assertDoesNotThrow(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         if (y == -2) break;
 | |
|       }
 | |
|       if (x == 2) break;
 | |
|     }
 | |
|   }, -3);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|       }
 | |
|     }
 | |
|   }, -3);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         if (y == -2) break;
 | |
|       }
 | |
|     }
 | |
|   }, 3);
 | |
| 
 | |
|   assertDoesNotThrow(() => {
 | |
|     l: for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         if (y == -2) break l;
 | |
|       }
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         throw 4;
 | |
|       }
 | |
|     }
 | |
|   }, 4);
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         if (y == -2) throw 4;
 | |
|       }
 | |
|     }
 | |
|   }, 4);
 | |
| 
 | |
|   let log = [];
 | |
|   g1.prototype.return = () => { log.push(1); throw 5 };
 | |
|   g2.prototype.return = () => { log.push(2); throw -5 };
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         if (y == -2) break;
 | |
|       }
 | |
|       if (x == 2) break;
 | |
|     }
 | |
|   }, -5);
 | |
|   assertEquals([2, 1], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|       }
 | |
|     }
 | |
|   }, -3);
 | |
|   assertEquals([1], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         if (y == -2) break;
 | |
|       }
 | |
|     }
 | |
|   }, -5);
 | |
|   assertEquals([2, 1], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     l: for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         if (y == -2) break l;
 | |
|       }
 | |
|     }
 | |
|   }, -5);
 | |
|   assertEquals([2, 1], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         throw 4;
 | |
|       }
 | |
|     }
 | |
|   }, 4);
 | |
|   assertEquals([2, 1], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       for (let y of g2()) {
 | |
|         if (y == -2) throw 4;
 | |
|       }
 | |
|     }
 | |
|   }, 4);
 | |
|   assertEquals([2, 1], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       try {
 | |
|         for (let y of g2()) {
 | |
|         }
 | |
|       } catch (_) {}
 | |
|     }
 | |
|   }, 3);
 | |
|   assertEquals([], log);
 | |
| 
 | |
|   log = [];
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g1()) {
 | |
|       try {
 | |
|         for (let y of g2()) {
 | |
|         }
 | |
|       } catch (_) {}
 | |
|       if (x == 2) break;
 | |
|     }
 | |
|   }, 5);
 | |
|   assertEquals([1], log);
 | |
| }
 | |
| 
 | |
| 
 | |
| // yield*, argument's return method is "undefined".
 | |
| function TestYieldStarWithoutReturn(get_iterable) {
 | |
|   assertTrue(get_iterable().return == undefined);
 | |
| 
 | |
|   function* g() { yield* get_iterable() }
 | |
| 
 | |
|   {
 | |
|     let gen = g();
 | |
|     assertEquals({value: 1, done: false}, gen.next());
 | |
|     assertEquals({value: undefined, done: true}, gen.return());
 | |
|   }
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     for (let x of g()) break;
 | |
|     return 42;
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     for (let x of g()) return 42;
 | |
|   })());
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) throw 42;
 | |
|   }, 42);
 | |
| }
 | |
| {
 | |
|   let get_iterable1 = () => [1, 2];
 | |
|   let get_iterable2 = function*() { yield 1; yield 2 };
 | |
|   get_iterable2.prototype.return = null;
 | |
|   TestYieldStarWithoutReturn(get_iterable1);
 | |
|   TestYieldStarWithoutReturn(get_iterable2);
 | |
| }
 | |
| 
 | |
| 
 | |
| // yield*, argument's return method is defined.
 | |
| {
 | |
|   let get_iterable = function*() { yield 1; yield 2 };
 | |
|   const obj = {};
 | |
|   get_iterable.prototype.return = (...args) => obj;
 | |
| 
 | |
|   function* g() { yield* get_iterable() }
 | |
| 
 | |
|   {
 | |
|     let gen = g();
 | |
|     assertEquals({value: 1, done: false}, gen.next());
 | |
|     assertSame(obj, gen.return());
 | |
|     assertSame(obj, gen.return());
 | |
|     assertSame(obj, gen.return());
 | |
|     assertEquals({value: 2, done: false}, gen.next());
 | |
|     assertSame(obj, gen.return());
 | |
|     assertSame(obj, gen.return());
 | |
|     assertSame(obj, gen.return());
 | |
|     assertEquals({value: undefined, done: true}, gen.next());
 | |
|     assertEquals({value: undefined, done: true}, gen.return());
 | |
|     assertEquals({value: undefined, done: true}, gen.return());
 | |
|   }
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     for (let x of g()) break;
 | |
|     return 42;
 | |
|   })());
 | |
| 
 | |
|   assertEquals(42, (() => {
 | |
|     for (let x of g()) return 42;
 | |
|   })());
 | |
| 
 | |
|   assertThrowsEquals(() => {
 | |
|     for (let x of g()) throw 42;
 | |
|   }, 42);
 | |
| }
 |