diff options
Diffstat (limited to 'js/src/tests/non262/Reflect/construct.js')
-rw-r--r-- | js/src/tests/non262/Reflect/construct.js | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/js/src/tests/non262/Reflect/construct.js b/js/src/tests/non262/Reflect/construct.js new file mode 100644 index 0000000000..7dbb9bfa7d --- /dev/null +++ b/js/src/tests/non262/Reflect/construct.js @@ -0,0 +1,107 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Reflect.construct invokes constructors. + +assertDeepEq(Reflect.construct(Object, []), {}); +assertDeepEq(Reflect.construct(String, ["hello"]), new String("hello")); + +// Constructing Date creates a real Date object. +var d = Reflect.construct(Date, [1776, 6, 4]); +assertEq(d instanceof Date, true); +assertEq(d.getFullYear(), 1776); // non-generic method requires real Date object + +// [[Construct]] methods don't necessarily create new objects. +var obj = {}; +assertEq(Reflect.construct(Object, [obj]), obj); + + +// === Various kinds of constructors +// We've already seen some builtin constructors. +// +// JS functions: +function f(x) { this.x = x; } +assertDeepEq(Reflect.construct(f, [3]), new f(3)); +f.prototype = Array.prototype; +assertDeepEq(Reflect.construct(f, [3]), new f(3)); + +// Bound functions: +var bound = f.bind(null, "carrot"); +assertDeepEq(Reflect.construct(bound, []), new bound); + +// Classes: +class Base { + constructor(...args) { + this.args = args; + this.newTarget = new.target; + } +} +class Derived extends Base { + constructor(...args) { super(...args); } +} + +assertDeepEq(Reflect.construct(Base, []), new Base); +assertDeepEq(Reflect.construct(Derived, [7]), new Derived(7)); +g = Derived.bind(null, "q"); +assertDeepEq(Reflect.construct(g, [8, 9]), new g(8, 9)); + +// Cross-compartment wrappers: +var g = newGlobal(); +var local = {here: this}; +g.eval("function F(arg) { this.arg = arg }"); +assertDeepEq(Reflect.construct(g.F, [local]), new g.F(local)); + +// If first argument to Reflect.construct isn't a constructor, it throws a +// TypeError. +var nonConstructors = [ + {}, + Reflect.construct, // builtin functions aren't constructors + x => x + 1, + Math.max.bind(null, 0), // bound non-constructors aren't constructors + ((x, y) => x > y).bind(null, 0), + + // A Proxy to a non-constructor function isn't a constructor, even if a + // construct handler is present. + new Proxy(Reflect.construct, {construct(){}}), +]; +for (var obj of nonConstructors) { + assertThrowsInstanceOf(() => Reflect.construct(obj, []), TypeError); + assertThrowsInstanceOf(() => Reflect.construct(obj, [], Object), TypeError); +} + + +// === new.target tests + +// If the newTarget argument to Reflect.construct is missing, the target is used. +function checkNewTarget() { + assertEq(new.target, expected); + expected = undefined; +} +var expected = checkNewTarget; +Reflect.construct(checkNewTarget, []); + +// The newTarget argument is correctly passed to the constructor. +var constructors = [Object, Function, f, bound]; +for (var ctor of constructors) { + expected = ctor; + Reflect.construct(checkNewTarget, [], ctor); + assertEq(expected, undefined); +} + +// The newTarget argument must be a constructor. +for (var v of SOME_PRIMITIVE_VALUES.concat(nonConstructors)) { + assertThrowsInstanceOf(() => Reflect.construct(checkNewTarget, [], v), TypeError); +} + +// The builtin Array constructor uses new.target.prototype and always +// creates a real array object. +function someConstructor() {} +var result = Reflect.construct(Array, [], someConstructor); +assertEq(Reflect.getPrototypeOf(result), someConstructor.prototype); +assertEq(result.length, 0); +assertEq(Array.isArray(result), true); + + +// For more Reflect.construct tests, see target.js and argumentsList.js. + +reportCompare(0, 0); |