Home | History | Annotate | Download | only in es6
      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