mirror of
				https://github.com/tc39/test262.git
				synced 2025-10-27 01:33:59 +01:00 
			
		
		
		
	sourceRevisionAtLastExport: 33f2fb0e53d135f0ee17cfccd9d993eb2a6f47de targetRevisionAtLastExport: 31340cbd9add103f586d501b0c3354b7b182abc0
		
			
				
	
	
		
			510 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			510 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Copyright 2015 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.
 | |
| 
 | |
| // Flags: --allow-natives-syntax
 | |
| 
 | |
| function testSpreadCallsStrict() {
 | |
|   "use strict"
 | |
|   function countArgs() { return arguments.length; }
 | |
| 
 | |
|   // Test this argument
 | |
|   function returnThis() { return this; }
 | |
|   assertEquals(void 0, returnThis(..."test"));
 | |
| 
 | |
|   // Test argument counting with different iterables
 | |
|   assertEquals(0, countArgs(...""));
 | |
|   assertEquals(4, countArgs(..."test"));
 | |
|   assertEquals(4, countArgs(..."tes", ..."t"));
 | |
|   assertEquals(4, countArgs("t", ..."es", "t"));
 | |
|   assertEquals(4, countArgs("tes", ..."t!!"));
 | |
| 
 | |
|   assertEquals(1, countArgs(...[1]));
 | |
|   assertEquals(2, countArgs(...[1, 2]));
 | |
|   assertEquals(3, countArgs(...[1, 2, 3]));
 | |
|   assertEquals(4, countArgs(...[1, 2, 3, 4]));
 | |
|   assertEquals(5, countArgs(...[1, 2, 3, 4, 5]));
 | |
|   assertEquals(6, countArgs(...[1, 2, 3, 4, 5, 6]));
 | |
| 
 | |
|   assertEquals(1, countArgs(...[1.1]));
 | |
|   assertEquals(2, countArgs(...[1.1, 2.2]));
 | |
|   assertEquals(3, countArgs(...[1.1, 2.2, 3.3]));
 | |
|   assertEquals(4, countArgs(...[1.1, 2.2, 3.3, 4.4]));
 | |
|   assertEquals(5, countArgs(...[1.1, 2.2, 3.3, 4.4, 5.5]));
 | |
|   assertEquals(6, countArgs(...[1.1, 2.2, 3.3, 4.4, 5.5, 6.6]));
 | |
| 
 | |
|   assertEquals(1, countArgs(...new Set([1])));
 | |
|   assertEquals(2, countArgs(...new Set([1, 2])));
 | |
|   assertEquals(3, countArgs(...new Set([1, 2, 3])));
 | |
|   assertEquals(4, countArgs(...new Set([1, 2, 3, 4])));
 | |
|   assertEquals(5, countArgs(...new Set([1, 2, 3, 4, 5])));
 | |
|   assertEquals(6, countArgs(...new Set([1, 2, 3, 4, 5, 6])));
 | |
| 
 | |
|   assertEquals(3, countArgs(...(function*(){ yield 1; yield 2; yield 3; })()));
 | |
| 
 | |
|   // Test values
 | |
|   function sum() {
 | |
|     var sum = arguments[0];
 | |
|     for (var i = 1; i < arguments.length; ++i) {
 | |
|       sum += arguments[i];
 | |
|     }
 | |
|     return sum;
 | |
|   }
 | |
| 
 | |
|   assertThrows(function() {
 | |
|     sum(...0);
 | |
|   }, TypeError);
 | |
|   assertEquals(void 0, sum(...""));
 | |
|   assertEquals(void 0, sum(...[]));
 | |
|   assertEquals(void 0, sum(...new Set));
 | |
|   assertEquals(void 0, sum(...(function*() { })()));
 | |
| 
 | |
|   assertEquals("test", sum(..."test"));
 | |
|   assertEquals(10, sum(...[1, 2, 3, 4]));
 | |
|   assertEquals(10, sum(...[1, 2, 3], 4));
 | |
|   assertEquals(10, sum(1, ...[2, 3], 4));
 | |
|   assertEquals(10, sum(1, ...[2, 3], ...[4]));
 | |
|   assertEquals(10, sum(1, 2, ...[3, 4]));
 | |
|   assertEquals(10, sum(...new Set([1, 2, 3, 4])));
 | |
|   assertEquals(10, sum(...(function*() {
 | |
|     yield 1;
 | |
|     yield 2;
 | |
|     yield 3;
 | |
|     yield 4;
 | |
|   })()));
 | |
| 
 | |
|   // nested spreads
 | |
|   function makeArray() {
 | |
|     var result = [];
 | |
|     for (var i = 0; i < arguments.length; ++i) {
 | |
|       result.push(arguments[i]);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   assertEquals(10, sum(...makeArray(...[1, 2, 3, 4])));
 | |
|   assertEquals("test!!!", sum(...makeArray(..."test!!!")));
 | |
| 
 | |
|   // Interleaved spread/unspread args
 | |
|   assertEquals(36, sum(0, ...[1], 2, 3, ...[4, 5], 6, 7, 8));
 | |
|   assertEquals(45, sum(0, ...[1], 2, 3, ...[4, 5], 6, 7, 8, ...[9]));
 | |
| 
 | |
|   // Methods
 | |
|   var O = {
 | |
|     returnThis: returnThis,
 | |
|     countArgs: countArgs,
 | |
|     sum: sum,
 | |
|     makeArray: makeArray,
 | |
| 
 | |
|     nested: {
 | |
|       returnThis: returnThis,
 | |
|       countArgs: countArgs,
 | |
|       sum: sum,
 | |
|       makeArray: makeArray
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   // Test this argument
 | |
|   assertEquals(O, O.returnThis(..."test"));
 | |
|   assertEquals(O, O["returnThis"](..."test"));
 | |
|   assertEquals(O.nested, O.nested.returnThis(..."test"));
 | |
|   assertEquals(O.nested, O.nested["returnThis"](..."test"));
 | |
| 
 | |
|   // Test argument counting with different iterables
 | |
|   assertEquals(0, O.countArgs(...""));
 | |
|   assertEquals(4, O.countArgs(..."test"));
 | |
|   assertEquals(4, O.countArgs(..."tes", ..."t"));
 | |
|   assertEquals(4, O.countArgs("t", ..."es", "t"));
 | |
|   assertEquals(4, O.countArgs("tes", ..."t!!"));
 | |
| 
 | |
|   assertEquals(1, O.countArgs(...[1]));
 | |
|   assertEquals(2, O.countArgs(...[1, 2]));
 | |
|   assertEquals(3, O.countArgs(...[1, 2, 3]));
 | |
|   assertEquals(4, O.countArgs(...[1, 2, 3, 4]));
 | |
|   assertEquals(5, O.countArgs(...[1, 2, 3, 4, 5]));
 | |
|   assertEquals(6, O.countArgs(...[1, 2, 3, 4, 5, 6]));
 | |
| 
 | |
|   assertEquals(1, O.countArgs(...new Set([1])));
 | |
|   assertEquals(2, O.countArgs(...new Set([1, 2])));
 | |
|   assertEquals(3, O.countArgs(...new Set([1, 2, 3])));
 | |
|   assertEquals(4, O.countArgs(...new Set([1, 2, 3, 4])));
 | |
|   assertEquals(5, O.countArgs(...new Set([1, 2, 3, 4, 5])));
 | |
|   assertEquals(6, O.countArgs(...new Set([1, 2, 3, 4, 5, 6])));
 | |
| 
 | |
|   assertEquals(3, O.countArgs(
 | |
|       ...(function*(){ yield 1; yield 2; yield 3; })()));
 | |
| 
 | |
|   // Test values
 | |
|   assertEquals(void 0, O.sum(...""));
 | |
|   assertEquals(void 0, O.sum(...[]));
 | |
|   assertEquals(void 0, O.sum(...new Set));
 | |
|   assertEquals(void 0, O.sum(...(function*() { })()));
 | |
| 
 | |
|   assertEquals("test", O.sum(..."test"));
 | |
|   assertEquals(10, O.sum(...[1, 2, 3, 4]));
 | |
|   assertEquals(10, O.sum(...[1, 2, 3], 4));
 | |
|   assertEquals(10, O.sum(1, ...[2, 3], 4));
 | |
|   assertEquals(10, O.sum(1, ...[2, 3], ...[4]));
 | |
|   assertEquals(10, O.sum(1, 2, ...[3, 4]));
 | |
|   assertEquals(10, O.sum(...new Set([1, 2, 3, 4])));
 | |
|   assertEquals(10, O.sum(...(function*() {
 | |
|     yield 1;
 | |
|     yield 2;
 | |
|     yield 3;
 | |
|     yield 4;
 | |
|   })()));
 | |
| 
 | |
|   // nested spreads
 | |
|   assertEquals(10, O.sum(...O.makeArray(...[1, 2, 3, 4])));
 | |
|   assertEquals("test!!!", O.sum(...O.makeArray(..."test!!!")));
 | |
| 
 | |
|   // Interleaved spread/unspread args
 | |
|   assertEquals(36, O.sum(0, ...[1], 2, 3, ...[4, 5], 6, 7, 8));
 | |
|   assertEquals(45, O.sum(0, ...[1], 2, 3, ...[4, 5], 6, 7, 8, ...[9]));
 | |
| };
 | |
| testSpreadCallsStrict();
 | |
| %OptimizeFunctionOnNextCall(testSpreadCallsStrict);
 | |
| testSpreadCallsStrict();
 | |
| 
 | |
| 
 | |
| (function testSpreadCallsSloppy() {
 | |
|   // Test this argument
 | |
|   function returnThis() { return this; }
 | |
|   assertEquals(this, returnThis(..."test"));
 | |
| 
 | |
|   function countArgs() { return arguments.length; }
 | |
| 
 | |
|   // Test argument counting with different iterables
 | |
|   assertEquals(0, countArgs(...""));
 | |
|   assertEquals(4, countArgs(..."test"));
 | |
|   assertEquals(4, countArgs(..."tes", ..."t"));
 | |
|   assertEquals(4, countArgs("t", ..."es", "t"));
 | |
|   assertEquals(4, countArgs("tes", ..."t!!"));
 | |
| 
 | |
|   assertEquals(1, countArgs(...[1]));
 | |
|   assertEquals(2, countArgs(...[1, 2]));
 | |
|   assertEquals(3, countArgs(...[1, 2, 3]));
 | |
|   assertEquals(4, countArgs(...[1, 2, 3, 4]));
 | |
|   assertEquals(5, countArgs(...[1, 2, 3, 4, 5]));
 | |
|   assertEquals(6, countArgs(...[1, 2, 3, 4, 5, 6]));
 | |
| 
 | |
|   assertEquals(1, countArgs(...new Set([1])));
 | |
|   assertEquals(2, countArgs(...new Set([1, 2])));
 | |
|   assertEquals(3, countArgs(...new Set([1, 2, 3])));
 | |
|   assertEquals(4, countArgs(...new Set([1, 2, 3, 4])));
 | |
|   assertEquals(5, countArgs(...new Set([1, 2, 3, 4, 5])));
 | |
|   assertEquals(6, countArgs(...new Set([1, 2, 3, 4, 5, 6])));
 | |
| 
 | |
|   assertEquals(3, countArgs(...(function*(){
 | |
|     yield 1;
 | |
|     yield 2;
 | |
|     yield 3;
 | |
|   })()));
 | |
| 
 | |
|   // Test values
 | |
|   function sum() {
 | |
|     var sum = arguments[0];
 | |
|     for (var i = 1; i < arguments.length; ++i) {
 | |
|       sum += arguments[i];
 | |
|     }
 | |
|     return sum;
 | |
|   }
 | |
| 
 | |
|   assertThrows(function() {
 | |
|     sum(...0);
 | |
|   }, TypeError);
 | |
|   assertEquals(void 0, sum(...""));
 | |
|   assertEquals(void 0, sum(...[]));
 | |
|   assertEquals(void 0, sum(...new Set));
 | |
|   assertEquals(void 0, sum(...(function*() { })()));
 | |
| 
 | |
|   assertEquals("test", sum(..."test"));
 | |
|   assertEquals(10, sum(...[1, 2, 3, 4]));
 | |
|   assertEquals(10, sum(...[1, 2, 3], 4));
 | |
|   assertEquals(10, sum(1, ...[2, 3], 4));
 | |
|   assertEquals(10, sum(1, ...[2, 3], ...[4]));
 | |
|   assertEquals(10, sum(1, 2, ...[3, 4]));
 | |
|   assertEquals(10, sum(...new Set([1, 2, 3, 4])));
 | |
|   assertEquals(10, sum(...(function*() {
 | |
|     yield 1;
 | |
|     yield 2;
 | |
|     yield 3;
 | |
|     yield 4;
 | |
|   })()));
 | |
| 
 | |
|   // nested spreads
 | |
|   function makeArray() {
 | |
|     var result = [];
 | |
|     for (var i = 0; i < arguments.length; ++i) {
 | |
|       result.push(arguments[i]);
 | |
|     }
 | |
|     return result;
 | |
|   }
 | |
|   assertEquals(10, sum(...makeArray(...[1, 2, 3, 4])));
 | |
|   assertEquals("test!!!", sum(...makeArray(..."test!!!")));
 | |
| 
 | |
|   // Interleaved spread/unspread args
 | |
|   assertEquals(36, sum(0, ...[1], 2, 3, ...[4, 5], 6, 7, 8));
 | |
|   assertEquals(45, sum(0, ...[1], 2, 3, ...[4, 5], 6, 7, 8, ...[9]));
 | |
| 
 | |
|   // Methods
 | |
|   var O = {
 | |
|     returnThis: returnThis,
 | |
|     countArgs: countArgs,
 | |
|     sum: sum,
 | |
|     makeArray: makeArray,
 | |
| 
 | |
|     nested: {
 | |
|       returnThis: returnThis,
 | |
|       countArgs: countArgs,
 | |
|       sum: sum,
 | |
|       makeArray: makeArray
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   // Test this argument
 | |
|   assertEquals(O, O.returnThis(..."test"));
 | |
|   assertEquals(O, O["returnThis"](..."test"));
 | |
|   assertEquals(O.nested, O.nested.returnThis(..."test"));
 | |
|   assertEquals(O.nested, O.nested["returnThis"](..."test"));
 | |
| 
 | |
|   // Test argument counting with different iterables
 | |
|   assertEquals(0, O.countArgs(...""));
 | |
|   assertEquals(4, O.countArgs(..."test"));
 | |
|   assertEquals(4, O.countArgs(..."tes", ..."t"));
 | |
|   assertEquals(4, O.countArgs("t", ..."es", "t"));
 | |
|   assertEquals(4, O.countArgs("tes", ..."t!!"));
 | |
| 
 | |
|   assertEquals(1, O.countArgs(...[1]));
 | |
|   assertEquals(2, O.countArgs(...[1, 2]));
 | |
|   assertEquals(3, O.countArgs(...[1, 2, 3]));
 | |
|   assertEquals(4, O.countArgs(...[1, 2, 3, 4]));
 | |
|   assertEquals(5, O.countArgs(...[1, 2, 3, 4, 5]));
 | |
|   assertEquals(6, O.countArgs(...[1, 2, 3, 4, 5, 6]));
 | |
| 
 | |
|   assertEquals(1, O.countArgs(...new Set([1])));
 | |
|   assertEquals(2, O.countArgs(...new Set([1, 2])));
 | |
|   assertEquals(3, O.countArgs(...new Set([1, 2, 3])));
 | |
|   assertEquals(4, O.countArgs(...new Set([1, 2, 3, 4])));
 | |
|   assertEquals(5, O.countArgs(...new Set([1, 2, 3, 4, 5])));
 | |
|   assertEquals(6, O.countArgs(...new Set([1, 2, 3, 4, 5, 6])));
 | |
| 
 | |
|   assertEquals(3, O.countArgs(...(function*(){
 | |
|     yield 1;
 | |
|     yield 2;
 | |
|     yield 3;
 | |
|   })()));
 | |
| 
 | |
|   // Test values
 | |
|   assertEquals(void 0, O.sum(...""));
 | |
|   assertEquals(void 0, O.sum(...[]));
 | |
|   assertEquals(void 0, O.sum(...new Set));
 | |
|   assertEquals(void 0, O.sum(...(function*() { })()));
 | |
| 
 | |
|   assertEquals("test", O.sum(..."test"));
 | |
|   assertEquals(10, O.sum(...[1, 2, 3, 4]));
 | |
|   assertEquals(10, O.sum(...[1, 2, 3], 4));
 | |
|   assertEquals(10, O.sum(1, ...[2, 3], 4));
 | |
|   assertEquals(10, O.sum(1, ...[2, 3], ...[4]));
 | |
|   assertEquals(10, O.sum(1, 2, ...[3, 4]));
 | |
|   assertEquals(10, O.sum(...new Set([1, 2, 3, 4])));
 | |
|   assertEquals(10, O.sum(...(function*() {
 | |
|     yield 1;
 | |
|     yield 2;
 | |
|     yield 3;
 | |
|     yield 4;
 | |
|   })()));
 | |
| 
 | |
|   // nested spreads
 | |
|   assertEquals(10, O.sum(...O.makeArray(...[1, 2, 3, 4])));
 | |
|   assertEquals("test!!!", O.sum(...O.makeArray(..."test!!!")));
 | |
| 
 | |
|   // Interleaved spread/unspread args
 | |
|   assertEquals(36, O.sum(0, ...[1], 2, 3, ...[4, 5], 6, 7, 8));
 | |
|   assertEquals(45, O.sum(0, ...[1], 2, 3, ...[4, 5], 6, 7, 8, ...[9]));
 | |
| })();
 | |
| 
 | |
| 
 | |
| (function testSpreadEvaluationOrder() {
 | |
|   "use strict";
 | |
|   var log = "";
 | |
|   function* gen() { log += "X"; yield 0; log += "Y"; }
 | |
|   function a() { log += "A"; }
 | |
|   function b() { log += "B"; return gen(); }
 | |
|   function* c() { log += 'C1'; yield 1; log += 'C2'; }
 | |
|   function d() { log += "D"; }
 | |
|   function e() { log += "E"; }
 | |
|   function fn() {
 | |
|     var args = [];
 | |
|     for (var i = 0; i < arguments.length; ++i) args.push(arguments[i]);
 | |
|     return args;
 | |
|   }
 | |
| 
 | |
|   var result = fn(a(), ...b(), d());
 | |
|   assertEquals([undefined, 0, undefined], result);
 | |
|   assertEquals("ABXYD", log);
 | |
| 
 | |
|   log = "";
 | |
|   result = fn(...b(), d());
 | |
|   assertEquals([0, undefined], result);
 | |
|   assertEquals("BXYD", log);
 | |
| 
 | |
|   log = "";
 | |
|   result = fn(a(), ...b());
 | |
|   assertEquals([undefined, 0], result);
 | |
|   assertEquals("ABXY", log);
 | |
| 
 | |
|   log = "";
 | |
|   result = fn(a(), ...b(), ...c(), d(), e());
 | |
|   assertEquals([undefined, 0, 1, undefined, undefined], result);
 | |
|   assertEquals("ABXYC1C2DE", log);
 | |
| 
 | |
|   log = "";
 | |
|   result = fn(a(), ...b(), ...c(), d(), e(), ...b(), ...c());
 | |
|   assertEquals([undefined, 0, 1, undefined, undefined, 0, 1], result);
 | |
|   assertEquals("ABXYC1C2DEBXYC1C2", log);
 | |
| })();
 | |
| 
 | |
| (function testArrayPrototypeHoleGetterModifiesIteratorPrototypeNext() {
 | |
|   function sum() {
 | |
|     var sum = arguments[0];
 | |
|     for (var i = 1; i < arguments.length; ++i) {
 | |
|       sum += arguments[i];
 | |
|     }
 | |
|     return sum;
 | |
|   }
 | |
|   var a = [1, 2];
 | |
|   a[3] = 4;
 | |
|   var called = 0;
 | |
| 
 | |
|   // .next method is only accessed during iteration prologue (see
 | |
|   // https://github.com/tc39/ecma262/pull/988)
 | |
|   let ArrayIteratorPrototype = Array.prototype[Symbol.iterator]().__proto__;
 | |
|   let ArrayIteratorPrototypeNextDescriptor =
 | |
|       Object.getOwnPropertyDescriptor(ArrayIteratorPrototype, 'next');
 | |
|   Object.defineProperty(Array.prototype, 2, {
 | |
|     get: function() {
 | |
|       var ai = a[Symbol.iterator]();
 | |
|       var original_next = ai.__proto__["next"];
 | |
|       Object.defineProperty(ai.__proto__, "next", {
 | |
|         get: function() {
 | |
|           called++;
 | |
|           return original_next;
 | |
|         },
 | |
|         configurable: true
 | |
|       });
 | |
|       return 3;
 | |
|     },
 | |
|     configurable: true
 | |
|   });
 | |
| 
 | |
|   assertEquals(10, sum(...a));
 | |
|   assertEquals(0, called);
 | |
| 
 | |
|   Object.defineProperty(ArrayIteratorPrototype, 'next',
 | |
|                         ArrayIteratorPrototypeNextDescriptor);
 | |
|   Object.defineProperty(Array.prototype, 2, {});
 | |
| })();
 | |
| 
 | |
| (function testArrayHasOtherPrototype() {
 | |
|   function countArgs() { return arguments.length; }
 | |
|   var a = [1, 2, 3];
 | |
|   var b = {};
 | |
|   Object.defineProperty(b, Symbol.iterator, {
 | |
|     value: function*() {
 | |
|       yield 4;
 | |
|     },
 | |
|     configurable: true
 | |
|   });
 | |
| 
 | |
|   Object.setPrototypeOf(a, b);
 | |
| 
 | |
|   assertEquals(1, countArgs(...a));
 | |
| })();
 | |
| 
 | |
| (function testArrayIteratorPrototypeGetter() {
 | |
|   function countArgs() { return arguments.length; }
 | |
|   var a = [1, 2, 3];
 | |
|   var ai = a[Symbol.iterator]();
 | |
|   var called = 0;
 | |
| 
 | |
|   var original_next = ai.__proto__["next"];
 | |
| 
 | |
|   Object.defineProperty(ai.__proto__, "next", {
 | |
|     get: function() {
 | |
|       called++;
 | |
|       return original_next;
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   countArgs(...a);
 | |
| 
 | |
|   // .next method is only accessed during iteration prologue (see
 | |
|   // https://github.com/tc39/ecma262/pull/988)
 | |
|   assertEquals(1, called);
 | |
| })();
 | |
| 
 | |
| (function testArrayIteratorPrototypeModified() {
 | |
|   function countArgs() { return arguments.length; }
 | |
|   var a = [1,2,3];
 | |
|   var ai = a[Symbol.iterator]();
 | |
|   Object.defineProperty(ai.__proto__, "next", {
 | |
|     value: function() {
 | |
|       return {value: undefined, done: true};
 | |
|      },
 | |
|      configurable: true
 | |
|   });
 | |
| 
 | |
|   assertEquals(0, countArgs(...a));
 | |
| 
 | |
| })();
 | |
| 
 | |
| (function testCustomArrayPrototypeIterator() {
 | |
|   var origIterator =
 | |
|       Object.getOwnPropertyDescriptor(Array.prototype, Symbol.iterator);
 | |
|   Object.defineProperty(Array.prototype, Symbol.iterator, {
 | |
|     value: function*() {
 | |
|       yield 1;
 | |
|       yield 2;
 | |
|       yield 3;
 | |
|     },
 | |
|     configurable: true
 | |
|   });
 | |
|   function returnCountStrict() { 'use strict'; return arguments.length; }
 | |
|   function returnCountSloppy() { return arguments.length; }
 | |
| 
 | |
|   assertEquals(3, returnCountStrict(...[1]));
 | |
|   assertEquals(4, returnCountStrict(1, ...[2]));
 | |
|   assertEquals(5, returnCountStrict(1, ...[2], 3));
 | |
|   assertEquals(3, returnCountSloppy(...[1]));
 | |
|   assertEquals(4, returnCountSloppy(1, ...[2]));
 | |
|   assertEquals(5, returnCountSloppy(1, ...[2], 3));
 | |
| 
 | |
|   Object.defineProperty(Array.prototype, Symbol.iterator, origIterator);
 | |
| })();
 | |
| 
 | |
| (function testGetPropertyIteratorCalledExactlyOnce() {
 | |
|   function countArgs() { return arguments.length; }
 | |
|   var a = [1, 2, 3];
 | |
|   var called = 0;
 | |
| 
 | |
|   Object.defineProperty(Array.prototype, Symbol.iterator, {
 | |
|     value: function*() {
 | |
|       yield 1;
 | |
|       yield 2;
 | |
|     },
 | |
|     configurable: true
 | |
|   });
 | |
| 
 | |
|   var it = a[Symbol.iterator];
 | |
|   Object.defineProperty(a, Symbol.iterator, {
 | |
|     get: function() {
 | |
|       called++;
 | |
|       return it;
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   countArgs(...a);
 | |
| 
 | |
|   assertEquals(1, called);
 | |
| })();
 |