| // Copyright 2014 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 testRestIndex() { | 
 |   assertEquals(5, (function(...args) { return args.length; })(1,2,3,4,5)); | 
 |   assertEquals(4, (function(a, ...args) { return args.length; })(1,2,3,4,5)); | 
 |   assertEquals(3, (function(a, b, ...args) { return args.length; })(1,2,3,4,5)); | 
 |   assertEquals(2, (function(a, b, c, ...args) { | 
 |                       return args.length; })(1,2,3,4,5)); | 
 |   assertEquals(1, (function(a, b, c, d, ...args) { | 
 |                       return args.length; })(1,2,3,4,5)); | 
 |   assertEquals(0, (function(a, b, c, d, e, ...args) { | 
 |                     return args.length; })(1,2,3,4,5)); | 
 | })(); | 
 |  | 
 |  | 
 | var strictTest = (function() { | 
 |   "use strict"; | 
 |   return function strictTest(a, b, ...c) { | 
 |     assertEquals(Array, c.constructor); | 
 |     assertTrue(Array.isArray(c)); | 
 |  | 
 |     var expectedLength = arguments.length >= 3 ? arguments.length - 2 : 0; | 
 |     assertEquals(expectedLength, c.length); | 
 |  | 
 |     for (var i = 2, j = 0; i < arguments.length; ++i) { | 
 |       assertEquals(c[j++], arguments[i]); | 
 |     } | 
 |   }; | 
 | })(); | 
 |  | 
 |  | 
 | function sloppyTest(a, b, ...c) { | 
 |   assertEquals(Array, c.constructor); | 
 |   assertTrue(Array.isArray(c)); | 
 |  | 
 |   var expectedLength = arguments.length >= 3 ? arguments.length - 2 : 0; | 
 |   assertEquals(expectedLength, c.length); | 
 |  | 
 |   for (var i = 2, j = 0; i < arguments.length; ++i) { | 
 |     assertEquals(c[j++], arguments[i]); | 
 |   } | 
 | } | 
 |  | 
 |  | 
 | var O = { | 
 |   strict: strictTest, | 
 |   sloppy: sloppyTest | 
 | }; | 
 |  | 
 | (function testStrictRestParamArity() { | 
 |   assertEquals(2, strictTest.length); | 
 |   assertEquals(2, O.strict.length); | 
 | })(); | 
 |  | 
 |  | 
 | (function testRestParamsStrictMode() { | 
 |   strictTest(); | 
 |   strictTest(1, 2); | 
 |   strictTest(1, 2, 3, 4, 5, 6); | 
 |   strictTest(1, 2, 3); | 
 |   O.strict(); | 
 |   O.strict(1, 2); | 
 |   O.strict(1, 2, 3, 4, 5, 6); | 
 |   O.strict(1, 2, 3); | 
 | })(); | 
 |  | 
 |  | 
 | (function testRestParamsStrictModeApply() { | 
 |   strictTest.apply(null, []); | 
 |   strictTest.apply(null, [1, 2]); | 
 |   strictTest.apply(null, [1, 2, 3, 4, 5, 6]); | 
 |   strictTest.apply(null, [1, 2, 3]); | 
 |   O.strict.apply(O, []); | 
 |   O.strict.apply(O, [1, 2]); | 
 |   O.strict.apply(O, [1, 2, 3, 4, 5, 6]); | 
 |   O.strict.apply(O, [1, 2, 3]); | 
 | })(); | 
 |  | 
 |  | 
 | (function testRestParamsStrictModeCall() { | 
 |   strictTest.call(null); | 
 |   strictTest.call(null, 1, 2); | 
 |   strictTest.call(null, 1, 2, 3, 4, 5, 6); | 
 |   strictTest.call(null, 1, 2, 3); | 
 |   O.strict.call(O); | 
 |   O.strict.call(O, 1, 2); | 
 |   O.strict.call(O, 1, 2, 3, 4, 5, 6); | 
 |   O.strict.call(O, 1, 2, 3); | 
 | })(); | 
 |  | 
 |  | 
 | (function testsloppyRestParamArity() { | 
 |   assertEquals(2, sloppyTest.length); | 
 |   assertEquals(2, O.sloppy.length); | 
 | })(); | 
 |  | 
 |  | 
 | (function testRestParamssloppyMode() { | 
 |   sloppyTest(); | 
 |   sloppyTest(1, 2); | 
 |   sloppyTest(1, 2, 3, 4, 5, 6); | 
 |   sloppyTest(1, 2, 3); | 
 |   O.sloppy(); | 
 |   O.sloppy(1, 2); | 
 |   O.sloppy(1, 2, 3, 4, 5, 6); | 
 |   O.sloppy(1, 2, 3); | 
 | })(); | 
 |  | 
 |  | 
 | (function testRestParamssloppyModeApply() { | 
 |   sloppyTest.apply(null, []); | 
 |   sloppyTest.apply(null, [1, 2]); | 
 |   sloppyTest.apply(null, [1, 2, 3, 4, 5, 6]); | 
 |   sloppyTest.apply(null, [1, 2, 3]); | 
 |   O.sloppy.apply(O, []); | 
 |   O.sloppy.apply(O, [1, 2]); | 
 |   O.sloppy.apply(O, [1, 2, 3, 4, 5, 6]); | 
 |   O.sloppy.apply(O, [1, 2, 3]); | 
 | })(); | 
 |  | 
 |  | 
 | (function testRestParamssloppyModeCall() { | 
 |   sloppyTest.call(null); | 
 |   sloppyTest.call(null, 1, 2); | 
 |   sloppyTest.call(null, 1, 2, 3, 4, 5, 6); | 
 |   sloppyTest.call(null, 1, 2, 3); | 
 |   O.sloppy.call(O); | 
 |   O.sloppy.call(O, 1, 2); | 
 |   O.sloppy.call(O, 1, 2, 3, 4, 5, 6); | 
 |   O.sloppy.call(O, 1, 2, 3); | 
 | })(); | 
 |  | 
 |  | 
 | (function testUnmappedArguments() { | 
 |   // Strict/Unmapped arguments should always be used for functions with rest | 
 |   // parameters | 
 |   assertThrows(function(...rest) { return arguments.callee; }, TypeError); | 
 |   // TODO(caitp): figure out why this doesn't throw sometimes, even though the | 
 |   //              getter always does =) | 
 |   // assertThrows(function(...rest) { arguments.callee = 1; }, TypeError); | 
 | })(); | 
 |  | 
 |  | 
 | (function testNoAliasArgumentsStrict() { | 
 |   ((function() { | 
 |     "use strict"; | 
 |     return (function strictF(a, ...rest) { | 
 |               arguments[0] = 1; | 
 |               assertEquals(3, a); | 
 |               arguments[1] = 2; | 
 |               assertArrayEquals([4, 5], rest); | 
 |             }); | 
 |   })())(3, 4, 5); | 
 | })(); | 
 |  | 
 |  | 
 | (function testNoAliasArgumentsSloppy() { | 
 |   function sloppyF(a, ...rest) { | 
 |     arguments[0] = 1; | 
 |     assertEquals(3, a); | 
 |     arguments[1] = 2; | 
 |     assertArrayEquals([4, 5], rest); | 
 |   } | 
 |   sloppyF(3, 4, 5); | 
 | })(); | 
 |  | 
 |  | 
 | (function testRestParamsWithNewTarget() { | 
 |   "use strict"; | 
 |   class Base { | 
 |     constructor(...a) { | 
 |       this.base = a; | 
 |       assertEquals(arguments.length, a.length); | 
 |       var args = []; | 
 |       for (var i = 0; i < arguments.length; ++i) { | 
 |         args.push(arguments[i]); | 
 |       } | 
 |       assertEquals(args, a); | 
 |     } | 
 |   } | 
 |   class Child extends Base { | 
 |     constructor(...b) { | 
 |       super(1, 2, 3); | 
 |       this.child = b; | 
 |       assertEquals(arguments.length, b.length); | 
 |       var args = []; | 
 |       for (var i = 0; i < arguments.length; ++i) { | 
 |         args.push(arguments[i]); | 
 |       } | 
 |       assertEquals(args, b); | 
 |     } | 
 |   } | 
 |  | 
 |   var c = new Child(1, 2, 3); | 
 |   assertEquals([1, 2, 3], c.child); | 
 |   assertEquals([1, 2, 3], c.base); | 
 | })(); | 
 |  | 
 | (function TestDirectiveThrows() { | 
 |   "use strict"; | 
 |  | 
 |   assertThrows( | 
 |     function(){ eval("function(...rest){'use strict';}") }, SyntaxError); | 
 |   assertThrows(function(){ eval("(...rest) => {'use strict';}") }, SyntaxError); | 
 |   assertThrows( | 
 |     function(){ eval("(class{foo(...rest) {'use strict';}});") }, SyntaxError); | 
 |  | 
 |   assertThrows( | 
 |     function(){ eval("function(a, ...rest){'use strict';}") }, SyntaxError); | 
 |   assertThrows( | 
 |     function(){ eval("(a, ...rest) => {'use strict';}") }, SyntaxError); | 
 |   assertThrows( | 
 |     function(){ eval("(class{foo(a, ...rest) {'use strict';}});") }, | 
 |     SyntaxError); | 
 | })(); | 
 |  | 
 | (function TestRestArrayPattern() { | 
 |   function f(...[a, b, c]) { return a + b + c; } | 
 |   assertEquals(6, f(1, 2, 3)); | 
 |   assertEquals("123", f(1, "2", 3)); | 
 |   assertEquals(NaN, f(1)); | 
 |  | 
 |   var f2 = (...[a, b, c]) => a + b + c; | 
 |   assertEquals(6, f2(1, 2, 3)); | 
 |   assertEquals("123", f2(1, "2", 3)); | 
 |   assertEquals(NaN, f2(1)); | 
 | })(); | 
 |  | 
 | (function TestRestObjectPattern() { | 
 |   function f(...{length, 0: firstName, 1: lastName}) { | 
 |     return `Hello ${lastName}, ${firstName}! Called with ${length} args!`; | 
 |   } | 
 |   assertEquals("Hello Ross, Bob! Called with 4 args!", f("Bob", "Ross", 0, 0)); | 
 |  | 
 |   var f2 = (...{length, 0: firstName, 1: lastName}) => | 
 |       `Hello ${lastName}, ${firstName}! Called with ${length} args!`; | 
 |   assertEquals("Hello Ross, Bob! Called with 4 args!", f2("Bob", "Ross", 0, 0)); | 
 | })(); |