• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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; }
280  assertThrows(()=>Reflect.construct(f, [], g));
281})();
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})();
377