blob: b37f876e94ffb168646c6298be81cc778785877c [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005
6(function testReflectConstructArity() {
7 assertEquals(2, Reflect.construct.length);
8})();
9
10
11(function testReflectConstructNonConstructor() {
12 assertThrows(function() {
13 new Reflect.construct(function(){}, []);
14 }, TypeError);
15})();
16
17
18(function testReflectConstructBasic() {
19 function Constructor() { "use strict"; }
20 assertInstanceof(Reflect.construct(Constructor, []), Constructor);
21})();
22
23
24(function testReflectConstructBasicSloppy() {
25 function Constructor() {}
26 assertInstanceof(Reflect.construct(Constructor, []), Constructor);
27})();
28
29
30(function testReflectConstructReturnSomethingElseStrict() {
31 var R = {};
32 function Constructor() { "use strict"; return R; }
33 assertSame(R, Reflect.construct(Constructor, []));
34})();
35
36
37(function testReflectConstructReturnSomethingElseSloppy() {
38 var R = {};
39 function Constructor() { return R; }
40 assertSame(R, Reflect.construct(Constructor, []));
41})();
42
43
44(function testReflectConstructNewTargetStrict() {
45 "use strict";
46 function Constructor() { this[9] = 1; }
47 var O = Reflect.construct(Constructor, [], Array);
48 assertEquals(1, O[9]);
49 // Ordinary object with Array.prototype --- no exotic Array magic
50 assertFalse(Array.isArray(O));
51 assertEquals(0, O.length);
52 assertSame(Array.prototype, Object.getPrototypeOf(O));
53})();
54
55
56(function testReflectConstructNewTargetSloppy() {
57 function Constructor() { this[9] = 1; }
58 var O = Reflect.construct(Constructor, [], Array);
59 assertEquals(1, O[9]);
60 // Ordinary object with Array.prototype --- no exotic Array magic
61 assertFalse(Array.isArray(O));
62 assertEquals(0, O.length);
63 assertSame(Array.prototype, Object.getPrototypeOf(O));
64})();
65
66
67(function testReflectConstructNewTargetStrict2() {
68 "use strict";
69 function Constructor() { this[9] = 1; }
70 Constructor.prototype.add = function(x) {
71 this[this.length] = x; return this;
72 }
73 var O = Reflect.construct(Array, [1, 2, 3], Constructor);
74 // Exotic Array object with Constructor.prototype
75 assertTrue(Array.isArray(O));
76 assertSame(Constructor.prototype, Object.getPrototypeOf(O));
77 assertFalse(O instanceof Array);
78 assertEquals(3, O.length);
79 assertEquals(undefined, O[9]);
80 assertSame(O, O.add(4));
81 assertEquals(4, O.length);
82 assertEquals(4, O[3]);
83})();
84
85
86(function testReflectConstructNewTargetSloppy2() {
87 function Constructor() { this[9] = 1; }
88 Constructor.prototype.add = function(x) {
89 this[this.length] = x; return this;
90 }
91 var O = Reflect.construct(Array, [1, 2, 3], Constructor);
92 // Exotic Array object with Constructor.prototype
93 assertTrue(Array.isArray(O));
94 assertSame(Constructor.prototype, Object.getPrototypeOf(O));
95 assertFalse(O instanceof Array);
96 assertEquals(3, O.length);
97 assertEquals(undefined, O[9]);
98 assertSame(O, O.add(4));
99 assertEquals(4, O.length);
100 assertEquals(4, O[3]);
101})();
102
103
104(function testReflectConstructNewTargetStrict3() {
105 "use strict";
106 function A() {}
107 function B() {}
108 var O = Reflect.construct(A, [], B);
109 // TODO(caitp): bug: newTarget prototype is not used if it is not
110 // explicitly set.
111 //assertSame(B.prototype, Object.getPrototypeOf(O));
112})();
113
114
115(function testReflectConstructNewTargetSloppy3() {
116 function A() {}
117 function B() {}
118 var O = Reflect.construct(A, [], B);
119 // TODO(caitp): bug: newTarget prototype is not used if it is not
120 // explicitly set.
121 //assertSame(B.prototype, Object.getPrototypeOf(O));
122})();
123
124
125(function testAppliedArgumentsLength() {
126 function lengthStrict() { 'use strict'; this.a = arguments.length; }
127 function lengthSloppy() { this.a = arguments.length; }
128
129 assertEquals(0, Reflect.construct(lengthStrict, []).a);
130 assertEquals(0, Reflect.construct(lengthSloppy, []).a);
131 assertEquals(0, Reflect.construct(lengthStrict, {}).a);
132 assertEquals(0, Reflect.construct(lengthSloppy, {}).a);
133
134 for (var i = 0; i < 256; ++i) {
135 assertEquals(i, Reflect.construct(lengthStrict, new Array(i)).a);
136 assertEquals(i, Reflect.construct(lengthSloppy, new Array(i)).a);
137 assertEquals(i, Reflect.construct(lengthStrict, { length: i }).a);
138 assertEquals(i, Reflect.construct(lengthSloppy, { length: i }).a);
139 }
140})();
141
142
143(function testAppliedArgumentsLengthThrows() {
144 function noopStrict() { 'use strict'; }
145 function noopSloppy() { }
146 function MyError() {}
147
148 var argsList = {};
149 Object.defineProperty(argsList, "length", {
150 get: function() { throw new MyError(); }
151 });
152
153 assertThrows(function() {
154 Reflect.construct(noopStrict, argsList);
155 }, MyError);
156
157 assertThrows(function() {
158 Reflect.construct(noopSloppy, argsList);
159 }, MyError);
160})();
161
162
163(function testAppliedArgumentsElementThrows() {
164 function noopStrict() { 'use strict'; }
165 function noopSloppy() { }
166 function MyError() {}
167
168 var argsList = { length: 1 };
169 Object.defineProperty(argsList, "0", {
170 get: function() { throw new MyError(); }
171 });
172
173 assertThrows(function() {
174 Reflect.construct(noopStrict, argsList);
175 }, MyError);
176
177 assertThrows(function() {
178 Reflect.construct(noopSloppy, argsList);
179 }, MyError);
180})();
181
182
183(function testAppliedNonFunctionStrict() {
184 'use strict';
185 assertThrows(function() { Reflect.construct(void 0, []); }, TypeError);
186 assertThrows(function() { Reflect.construct(null, []); }, TypeError);
187 assertThrows(function() { Reflect.construct(123, []); }, TypeError);
188 assertThrows(function() { Reflect.construct("str", []); }, TypeError);
189 assertThrows(function() { Reflect.construct(Symbol("x"), []); }, TypeError);
190 assertThrows(function() { Reflect.construct(/123/, []); }, TypeError);
191 assertThrows(function() { Reflect.construct(NaN, []); }, TypeError);
192 assertThrows(function() { Reflect.construct({}, []); }, TypeError);
193 assertThrows(function() { Reflect.construct([], []); }, TypeError);
194})();
195
196
197(function testAppliedNonFunctionSloppy() {
198 assertThrows(function() { Reflect.construct(void 0, []); }, TypeError);
199 assertThrows(function() { Reflect.construct(null, []); }, TypeError);
200 assertThrows(function() { Reflect.construct(123, []); }, TypeError);
201 assertThrows(function() { Reflect.construct("str", []); }, TypeError);
202 assertThrows(function() { Reflect.construct(Symbol("x"), []); }, TypeError);
203 assertThrows(function() { Reflect.construct(/123/, []); }, TypeError);
204 assertThrows(function() { Reflect.construct(NaN, []); }, TypeError);
205 assertThrows(function() { Reflect.construct({}, []); }, TypeError);
206 assertThrows(function() { Reflect.construct([], []); }, TypeError);
207})();
208
209
210(function testAppliedArgumentsNonList() {
211 function noopStrict() { 'use strict'; }
212 function noopSloppy() {}
213 assertThrows(function() { Reflect.construct(noopStrict, null); }, TypeError);
214 assertThrows(function() { Reflect.construct(noopSloppy, null); }, TypeError);
215 assertThrows(function() { Reflect.construct(noopStrict, 1); }, TypeError);
216 assertThrows(function() { Reflect.construct(noopSloppy, 1); }, TypeError);
217 assertThrows(function() { Reflect.construct(noopStrict, "BAD"); }, TypeError);
218 assertThrows(function() { Reflect.construct(noopSloppy, "BAD"); }, TypeError);
219 assertThrows(function() { Reflect.construct(noopStrict, true); }, TypeError);
220 assertThrows(function() { Reflect.construct(noopSloppy, true); }, TypeError);
221 var sym = Symbol("x");
222 assertThrows(function() { Reflect.construct(noopStrict, sym); }, TypeError);
223 assertThrows(function() { Reflect.construct(noopSloppy, sym); }, TypeError);
224})();
225
226
227(function testAppliedArgumentValue() {
228 function firstStrict(a) { 'use strict'; this.a = a; }
229 function firstSloppy(a) { this.a = a; }
230 function lastStrict(a) {
231 'use strict'; this.a = arguments[arguments.length - 1]; }
232 function lastSloppy(a) { this.a = arguments[arguments.length - 1]; }
233 function sumStrict() {
234 'use strict';
235 var sum = arguments[0];
236 for (var i = 1; i < arguments.length; ++i) {
237 sum += arguments[i];
238 }
239 this.a = sum;
240 }
241 function sumSloppy() {
242 var sum = arguments[0];
243 for (var i = 1; i < arguments.length; ++i) {
244 sum += arguments[i];
245 }
246 this.a = sum;
247 }
248
249 assertEquals("OK!", Reflect.construct(firstStrict, ["OK!"]).a);
250 assertEquals("OK!", Reflect.construct(firstSloppy, ["OK!"]).a);
251 assertEquals("OK!", Reflect.construct(firstStrict,
252 { 0: "OK!", length: 1 }).a);
253 assertEquals("OK!", Reflect.construct(firstSloppy,
254 { 0: "OK!", length: 1 }).a);
255 assertEquals("OK!", Reflect.construct(lastStrict,
256 [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]).a);
257 assertEquals("OK!", Reflect.construct(lastSloppy,
258 [0, 1, 2, 3, 4, 5, 6, 7, 8, "OK!"]).a);
259 assertEquals("OK!", Reflect.construct(lastStrict,
260 { 9: "OK!", length: 10 }).a);
261 assertEquals("OK!", Reflect.construct(lastSloppy,
262 { 9: "OK!", length: 10 }).a);
263 assertEquals("TEST", Reflect.construct(sumStrict,
264 ["T", "E", "S", "T"]).a);
265 assertEquals("TEST!!", Reflect.construct(sumStrict,
266 ["T", "E", "S", "T", "!", "!"]).a);
267 assertEquals(10, Reflect.construct(sumStrict,
268 { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }).a);
269 assertEquals("TEST", Reflect.construct(sumSloppy,
270 ["T", "E", "S", "T"]).a);
271 assertEquals("TEST!!", Reflect.construct(sumSloppy,
272 ["T", "E", "S", "T", "!", "!"]).a);
273 assertEquals(10, Reflect.construct(sumSloppy,
274 { 0: 1, 1: 2, 2: 3, 3: 4, length: 4 }).a);
275})();
276
277(function() {
278 function* f() { yield 1; yield 2; }
279 function* g() { yield 3; yield 4; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100280 assertThrows(()=>Reflect.construct(f, [], g));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281})();
282
283(function () {
284 var realm1 = Realm.create();
285 var realm2 = Realm.create();
286
287 var well_known_intrinsic_constructors = [
288 "Array",
289 "ArrayBuffer",
290 "Boolean",
291 ["DataView", [new ArrayBuffer()]],
292 "Date",
293 "Error",
294 "EvalError",
295 "Float32Array",
296 "Float64Array",
297 ["Function", ["return 153;"]],
298 ["Function", ["'use strict'; return 153;"]],
299 ["Function", ["'use strong'; return 153;"]],
300 ["((function*(){}).constructor)", ["yield 153;"]], // GeneratorFunction
301 ["((function*(){}).constructor)", ["'use strict'; yield 153;"]],
302 ["((function*(){}).constructor)", ["'use strong'; yield 153;"]],
303 "Int8Array",
304 "Int16Array",
305 "Int32Array",
306 "Map",
307 "Number",
308 "Object",
309 ["Promise", [(resolve, reject)=>{}]],
310 "RangeError",
311 "ReferenceError",
312 "RegExp",
313 "Set",
314 "String",
315 "SyntaxError",
316 // %TypedArray%?
317 "TypeError",
318 "Uint8Array",
319 "Uint8ClampedArray",
320 "Uint16Array",
321 "Uint32Array",
322 "URIError",
323 "WeakMap",
324 "WeakSet"
325 ];
326
327 function getname(v) {
328 return typeof v === "string" ? v : v[0];
329 }
330
331 function getargs(v) {
332 return typeof v === "string" ? [] : v[1];
333 }
334
335 function test_intrinsic_prototype(name) {
336 var own = Realm.eval(realm1, name);
337
338 // Ensure that constructor.prototype is non-writable, non-configurable.
339 var desc = Object.getOwnPropertyDescriptor(own, "prototype");
340 assertFalse(desc.configurable, name);
341 assertFalse(desc.writable, name);
342 }
343
344 for (var intrinsic of well_known_intrinsic_constructors) {
345 test_intrinsic_prototype(getname(intrinsic));
346 }
347
348 function function_with_non_instance_prototype(realm) {
349 var f = Realm.eval(realm, "(function(){})");
350 f.prototype = 1;
351 return f;
352 }
353
354 function test_intrinsic_default(realm, name, args, convert) {
355 var own = Realm.eval(realm1, name);
356 var other = Realm.eval(realm, name);
357 var o = Reflect.construct(
358 convert(own), args, function_with_non_instance_prototype(realm));
359
360 // Ensure the intrisicDefaultProto is fetched from the correct realm.
361 assertTrue(realm == realm1 || o.__proto__ !== own.prototype, [...arguments]);
362 assertTrue(o.__proto__ === other.prototype, [...arguments]);
363 }
364
365 function test_all(test, convert) {
366 for (var intrinsic of well_known_intrinsic_constructors) {
367 for (var realm of [realm1, realm2]) {
368 test(realm, getname(intrinsic), getargs(intrinsic), convert);
369 }
370 }
371 }
372
373 test_all(test_intrinsic_default, (v)=>v);
374 test_all(test_intrinsic_default,
375 (v)=>{ "use strict"; return class extends v {}});
376})();