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