1// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Flags: --harmony-reflect
6
7
8(function testReflectApplyArity() {
9  assertEquals(3, Reflect.apply.length);
10})();
11
12
13(function testReflectApplyNonConstructor() {
14  assertThrows(function() {
15    new Reflect.apply(function(){}, null, []);
16  }, TypeError);
17})();
18
19
20(function testAppliedReceiverSloppy() {
21  function returnThis() { return this; }
22  var receiver = {};
23
24  assertSame(this, Reflect.apply(returnThis, void 0, []));
25  assertSame(this, Reflect.apply(returnThis, null, []));
26  assertSame(this, Reflect.apply(returnThis, this, []));
27  assertSame(receiver, Reflect.apply(returnThis, receiver, []));
28
29  // Wrap JS values
30  assertSame(String.prototype,
31             Object.getPrototypeOf(Reflect.apply(returnThis, "str", [])));
32  assertSame(Number.prototype,
33             Object.getPrototypeOf(Reflect.apply(returnThis, 123, [])));
34  assertSame(Boolean.prototype,
35             Object.getPrototypeOf(Reflect.apply(returnThis, true, [])));
36  assertSame(Symbol.prototype,
37             Object.getPrototypeOf(
38                Reflect.apply(returnThis, Symbol("test"), [])));
39})();
40
41
42(function testAppliedReceiverStrict() {
43  function returnThis() { 'use strict'; return this; }
44  var receiver = {};
45
46  assertSame(void 0, Reflect.apply(returnThis, void 0, []));
47  assertSame(this, Reflect.apply(returnThis, this, []));
48  assertSame(receiver, Reflect.apply(returnThis, receiver, []));
49
50  // Don't wrap value types
51  var regexp = /123/;
52  var symbol = Symbol("test");
53  assertSame("str", Reflect.apply(returnThis, "str", []));
54  assertSame(123, Reflect.apply(returnThis, 123, []));
55  assertSame(true, Reflect.apply(returnThis, true, []));
56  assertSame(regexp, Reflect.apply(returnThis, regexp, []));
57  assertSame(symbol, Reflect.apply(returnThis, symbol, []));
58})();
59
60
61(function testAppliedArgumentsLength() {
62  function returnLengthStrict() { 'use strict'; return arguments.length; }
63  function returnLengthSloppy() { return arguments.length; }
64
65  assertEquals(0, Reflect.apply(returnLengthStrict, this, []));
66  assertEquals(0, Reflect.apply(returnLengthSloppy, this, []));
67  assertEquals(0, Reflect.apply(returnLengthStrict, this, {}));
68  assertEquals(0, Reflect.apply(returnLengthSloppy, this, {}));
69
70  for (var i = 0; i < 256; ++i) {
71    assertEquals(i, Reflect.apply(returnLengthStrict, this, new Array(i)));
72    assertEquals(i, Reflect.apply(returnLengthSloppy, this, new Array(i)));
73    assertEquals(i, Reflect.apply(returnLengthStrict, this, { length: i }));
74    assertEquals(i, Reflect.apply(returnLengthSloppy, this, { length: i }));
75  }
76})();
77
78
79(function testAppliedArgumentsLengthThrows() {
80  function noopStrict() { 'use strict'; }
81  function noopSloppy() { }
82  function MyError() {}
83
84  var argsList = {};
85  Object.defineProperty(argsList, "length", {
86    get: function() { throw new MyError(); }
87  });
88
89  assertThrows(function() {
90    Reflect.apply(noopStrict, this, argsList);
91  }, MyError);
92
93  assertThrows(function() {
94    Reflect.apply(noopSloppy, this, argsList);
95  }, MyError);
96})();
97
98
99(function testAppliedArgumentsElementThrows() {
100  function noopStrict() { 'use strict'; }
101  function noopSloppy() { }
102  function MyError() {}
103
104  var argsList = { length: 1 };
105  Object.defineProperty(argsList, "0", {
106    get: function() { throw new MyError(); }
107  });
108
109  assertThrows(function() {
110    Reflect.apply(noopStrict, this, argsList);
111  }, MyError);
112
113  assertThrows(function() {
114    Reflect.apply(noopSloppy, this, argsList);
115  }, MyError);
116})();
117
118
119(function testAppliedNonFunctionStrict() {
120  'use strict';
121  assertThrows(function() { Reflect.apply(void 0); }, TypeError);
122  assertThrows(function() { Reflect.apply(null); }, TypeError);
123  assertThrows(function() { Reflect.apply(123); }, TypeError);
124  assertThrows(function() { Reflect.apply("str"); }, TypeError);
125  assertThrows(function() { Reflect.apply(Symbol("x")); }, TypeError);
126  assertThrows(function() { Reflect.apply(/123/); }, TypeError);
127  assertThrows(function() { Reflect.apply(NaN); }, TypeError);
128  assertThrows(function() { Reflect.apply({}); }, TypeError);
129  assertThrows(function() { Reflect.apply([]); }, TypeError);
130})();
131
132
133(function testAppliedNonFunctionSloppy() {
134  assertThrows(function() { Reflect.apply(void 0); }, TypeError);
135  assertThrows(function() { Reflect.apply(null); }, TypeError);
136  assertThrows(function() { Reflect.apply(123); }, TypeError);
137  assertThrows(function() { Reflect.apply("str"); }, TypeError);
138  assertThrows(function() { Reflect.apply(Symbol("x")); }, TypeError);
139  assertThrows(function() { Reflect.apply(/123/); }, TypeError);
140  assertThrows(function() { Reflect.apply(NaN); }, TypeError);
141  assertThrows(function() { Reflect.apply({}); }, TypeError);
142  assertThrows(function() { Reflect.apply([]); }, TypeError);
143})();
144
145
146(function testAppliedArgumentsNonList() {
147  function noopStrict() { 'use strict'; }
148  function noopSloppy() {}
149  var R = void 0;
150  assertThrows(function() { Reflect.apply(noopStrict, R, null); }, TypeError);
151  assertThrows(function() { Reflect.apply(noopSloppy, R, null); }, TypeError);
152  assertThrows(function() { Reflect.apply(noopStrict, R, 1); }, TypeError);
153  assertThrows(function() { Reflect.apply(noopSloppy, R, 1); }, TypeError);
154  assertThrows(function() { Reflect.apply(noopStrict, R, "BAD"); }, TypeError);
155  assertThrows(function() { Reflect.apply(noopSloppy, R, "BAD"); }, TypeError);
156  assertThrows(function() { Reflect.apply(noopStrict, R, true); }, TypeError);
157  assertThrows(function() { Reflect.apply(noopSloppy, R, true); }, TypeError);
158  var sym = Symbol("x");
159  assertThrows(function() { Reflect.apply(noopStrict, R, sym); }, TypeError);
160  assertThrows(function() { Reflect.apply(noopSloppy, R, sym); }, TypeError);
161})();
162
163
164(function testAppliedArgumentValue() {
165  function returnFirstStrict(a) { 'use strict'; return a; }
166  function returnFirstSloppy(a) { return a; }
167  function returnLastStrict(a) {
168    'use strict'; return arguments[arguments.length - 1]; }
169  function returnLastSloppy(a) { return arguments[arguments.length - 1]; }
170  function returnSumStrict() {
171    'use strict';
172    var sum = arguments[0];
173    for (var i = 1; i < arguments.length; ++i) {
174      sum += arguments[i];
175    }
176    return sum;
177  }
178  function returnSumSloppy() {
179    var sum = arguments[0];
180    for (var i = 1; i < arguments.length; ++i) {
181      sum += arguments[i];
182    }
183    return sum;
184  }
185
186  assertEquals("OK!", Reflect.apply(returnFirstStrict, this, ["OK!"]));
187  assertEquals("OK!", Reflect.apply(returnFirstSloppy, this, ["OK!"]));
188  assertEquals("OK!", Reflect.apply(returnFirstStrict, this,
189                                    { 0: "OK!", length: 1 }));
190  assertEquals("OK!", Reflect.apply(returnFirstSloppy, this,
191                                    { 0: "OK!", length: 1 }));
192  assertEquals("OK!", Reflect.apply(returnLastStrict, this,
193                                    [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]));
194  assertEquals("OK!", Reflect.apply(returnLastSloppy, this,
195                                    [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]));
196  assertEquals("OK!", Reflect.apply(returnLastStrict, this,
197                                    { 9: "OK!", length: 10 }));
198  assertEquals("OK!", Reflect.apply(returnLastSloppy, this,
199                                    { 9: "OK!", length: 10 }));
200  assertEquals("TEST", Reflect.apply(returnSumStrict, this,
201                                     ["T", "E", "S", "T"]));
202  assertEquals("TEST!!", Reflect.apply(returnSumStrict, this,
203                                       ["T", "E", "S", "T", "!", "!"]));
204  assertEquals(10, Reflect.apply(returnSumStrict, this,
205                                 { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }));
206  assertEquals("TEST", Reflect.apply(returnSumSloppy, this,
207                                     ["T", "E", "S", "T"]));
208  assertEquals("TEST!!", Reflect.apply(returnSumSloppy, this,
209                                       ["T", "E", "S", "T", "!", "!"]));
210  assertEquals(10, Reflect.apply(returnSumSloppy, this,
211                                 { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }));
212})();
213