function shouldBe(actual, expected) { if (actual !== expected) throw new Error('bad value: ' + actual); } function shouldThrow(func, message) { var error = null; try { func(); } catch (e) { error = e; } if (!error) throw new Error("not thrown."); if (String(error) !== message) throw new Error("bad error: " + String(error)); } shouldBe(Reflect.construct.length, 2); shouldThrow(() => { Reflect.construct("hello", 42); }, `TypeError: Reflect.construct requires the first argument be a constructor`); shouldThrow(() => { Reflect.construct(Array.prototype.forEach, []); }, `TypeError: Reflect.construct requires the first argument be a constructor`); shouldThrow(() => { Reflect.construct(function () { }, 42, null); }, `TypeError: Reflect.construct requires the third argument be a constructor if present`); shouldThrow(() => { Reflect.construct(function () { }, 42, {}); }, `TypeError: Reflect.construct requires the third argument be a constructor if present`); shouldThrow(() => { Reflect.construct(function () { }, 42, Array.prototype.forEach); }, `TypeError: Reflect.construct requires the third argument be a constructor if present`); shouldThrow(() => { Reflect.construct(function () { }, 42, function () { }); }, `TypeError: Reflect.construct requires the second argument be an object`); shouldThrow(() => { var array = { get length() { throw new Error("ok"); }, get 0() { throw new Error("ng"); } }; Reflect.construct(function () { }, array); }, `Error: ok`); shouldThrow(() => { var array = { get length() { return 1; }, get 0() { throw new Error("ok"); } }; Reflect.construct(function () { }, array); }, `Error: ok`); var array = { get length() { return 0; }, get 0() { throw new Error("ng"); } }; shouldBe(Reflect.construct(function () { this.length = arguments.length; }, array).length, 0); var globalObject = this; shouldBe(Reflect.construct(function Hello() { "use strict"; shouldBe(arguments[0], 0); shouldBe(arguments[1], 1); shouldBe(arguments[2], 2); shouldBe(typeof this, "object"); shouldBe(new.target, Hello); this.result = arguments.length; }, [0,1,2]).result, 3) shouldBe(Reflect.construct(function Hello() { shouldBe(arguments[0], 0); shouldBe(arguments[1], 1); shouldBe(arguments[2], 2); shouldBe(typeof this, "object"); shouldBe(new.target, Hello); this.result = arguments.length; }, [0,1,2]).result, 3) var newTarget = function () { }; shouldBe(Reflect.construct(function () { "use strict"; shouldBe(new.target, newTarget); this.result = arguments.length; }, [], newTarget).result, 0) shouldBe(Reflect.construct(function () { shouldBe(new.target, newTarget); this.result = arguments.length; }, [], newTarget).result, 0) { class A { constructor() { this.type = "A"; } } class B extends A { constructor() { super(); this.type = "B"; } } shouldBe(Reflect.construct(A, []).type, "A"); shouldBe(Reflect.construct(B, []).type, "B"); shouldBe(Reflect.construct(B, [], B).__proto__, B.prototype); shouldBe(Reflect.construct(B, [], A).__proto__, A.prototype); shouldBe(Reflect.construct(B, [], A).type, "B"); shouldBe(Reflect.construct(B, [], B).type, "B"); shouldBe(Reflect.construct(A, [], A).__proto__, A.prototype); shouldBe(Reflect.construct(A, [], B).__proto__, B.prototype); shouldBe(Reflect.construct(A, [], A).type, "A"); shouldBe(Reflect.construct(A, [], B).type, "A"); } function nativeConstructorTest() { class DerivedMap { } shouldBe(Reflect.construct(Map, [], DerivedMap).__proto__, DerivedMap.prototype); let map = Reflect.construct(Map, [], DerivedMap); map.__proto__ = Map.prototype; map.set(20, 30); shouldBe(map.get(20), 30); class FailedMap { } shouldBe(Reflect.construct(FailedMap, [], Map).__proto__, Map.prototype); shouldThrow(() => { let map = Reflect.construct(FailedMap, [], Map); map.set(20, 30); }, `TypeError: Map operation called on non-Map object`); shouldBe(Reflect.construct(Set, [], Map).__proto__, Map.prototype); shouldThrow(() => { let map = Reflect.construct(Set, [], Map); map.set(20, 30); }, `TypeError: Map operation called on non-Map object`); let set = Reflect.construct(Set, [], Map); Set.prototype.add.call(set, 20); shouldBe(Set.prototype.has.call(set, 20), true); } noInline(nativeConstructorTest); for (var i = 0; i < 1e4; ++i) nativeConstructorTest(); (function () { function Hello() { } let result = {}; let proxy = new Proxy(Hello, { construct(theTarget, argArray, newTarget) { shouldBe(newTarget, Map); shouldBe(theTarget, Hello); shouldBe(argArray.length, 2); shouldBe(argArray[0], 10); shouldBe(argArray[1], 20); return result; } }); shouldBe(Reflect.construct(proxy, [10, 20], Map), result); }()); (function () { var proxy = new Proxy(Map, { construct(theTarget, argArray, newTarget) { } }); var result = {}; function Hello() { shouldBe(new.target, proxy); shouldBe(new.target.prototype, Map.prototype); shouldBe(arguments.length, 2); shouldBe(arguments[0], 10); shouldBe(arguments[1], 20); return result; } shouldBe(Reflect.construct(Hello, [10, 20], proxy), result); }()); (function () { function Hello() { } var result = {}; var proxy1 = new Proxy(Hello, { construct(theTarget, argArray, newTarget) { shouldBe(newTarget, proxy2); shouldBe(theTarget, Hello); shouldBe(argArray.length, 2); shouldBe(argArray[0], 10); shouldBe(argArray[1], 20); return result; } }); var proxy2 = new Proxy(Map, { construct(theTarget, argArray, newTarget) { } }); shouldBe(Reflect.construct(proxy1, [10, 20], proxy2), result); }());