diff options
Diffstat (limited to 'js/src/tests/non262/Reflect/argumentsList.js')
-rw-r--r-- | js/src/tests/non262/Reflect/argumentsList.js | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/js/src/tests/non262/Reflect/argumentsList.js b/js/src/tests/non262/Reflect/argumentsList.js new file mode 100644 index 0000000000..1cd5984f00 --- /dev/null +++ b/js/src/tests/non262/Reflect/argumentsList.js @@ -0,0 +1,164 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Tests for the argumentList argument to Reflect.apply and Reflect.construct. + +// Reflect.apply and Reflect.construct require an argumentList argument that must be an object. +assertThrowsInstanceOf(() => Reflect.apply(Math.min, undefined), // missing + TypeError); +assertThrowsInstanceOf(() => Reflect.construct(Object), // missing + TypeError); +for (var primitive of SOME_PRIMITIVE_VALUES) { + assertThrowsInstanceOf(() => Reflect.apply(Math.min, undefined, primitive), + TypeError); + assertThrowsInstanceOf(() => Reflect.construct(Object, primitive), + TypeError); +} + +// Array used by several tests below. +var BOTH = [ + Reflect.apply, + // Adapt Reflect.construct to accept the same arguments as Reflect.apply. + (target, thisArgument, argumentList) => Reflect.construct(target, argumentList) +]; + +// The argumentList is copied and becomes the list of arguments passed to the function. +function getRest(...x) { return x; } +var args = [1, 2, 3]; +for (var method of BOTH) { + var result = method(getRest, undefined, args); + assertEq(result.join(), args.join()); + assertEq(result !== args, true); +} + +// argumentList.length can be less than func.length. +function testLess(a, b, c, d, e) { + assertEq(a, 1); + assertEq(b, true); + assertEq(c, "three"); + assertEq(d, Symbol.for); + assertEq(e, undefined); + + assertEq(arguments.length, 4); + assertEq(arguments !== args, true); + return "ok"; +} +args = [1, true, "three", Symbol.for]; +assertEq(Reflect.apply(testLess, undefined, args), "ok"); +assertEq(Reflect.construct(testLess, args) instanceof testLess, true); + +// argumentList.length can be more than func.length. +function testMoar(a) { + assertEq(a, args[0]); + return "good"; +} +assertEq(Reflect.apply(testMoar, undefined, args), "good"); +assertEq(Reflect.construct(testMoar, args) instanceof testMoar, true); + +// argumentList can be any object with a .length property. +function getArgs(...args) { + return args; +} +for (var method of BOTH) { + assertDeepEq(method(getArgs, undefined, {length: 0}), + []); + assertDeepEq(method(getArgs, undefined, {length: 1, "0": "zero"}), + ["zero"]); + assertDeepEq(method(getArgs, undefined, {length: 2}), + [undefined, undefined]); + assertDeepEq(method(getArgs, undefined, function (a, b, c) {}), + [undefined, undefined, undefined]); +} + +// The Iterable/Iterator interfaces are not used. +var funnyArgs = { + 0: "zero", + 1: "one", + length: 2, + [Symbol.iterator]() { throw "FAIL 1"; }, + next() { throw "FAIL 2"; } +}; +for (var method of BOTH) { + assertDeepEq(method(getArgs, undefined, funnyArgs), + ["zero", "one"]); +} + +// If argumentList has no .length property, no arguments are passed. +function count() { return {numArgsReceived: arguments.length}; } +for (var method of BOTH) { + assertEq(method(count, undefined, {"0": 0, "1": 1}).numArgsReceived, + 0); + function* g() { yield 1; yield 2; } + assertEq(method(count, undefined, g()).numArgsReceived, + 0); +} + +// If argumentsList.length has a getter, it is called. +var log; +args = { + get length() { log += "L"; return 1; }, + get "0"() { log += "0"; return "zero"; }, + get "1"() { log += "1"; return "one"; } +}; +for (var method of BOTH) { + log = ""; + assertDeepEq(method(getArgs, undefined, args), + ["zero"]); + assertEq(log, "L0"); +} + +// The argumentsList.length getter can throw; the exception is propagated. +var exc = {status: "bad"}; +args = { + get length() { throw exc; } +}; +for (var method of BOTH) { + assertThrowsValue(() => method(count, undefined, args), exc); +} + +// If argumentsList.length is unreasonably huge, we get an error. +// (This is an implementation limit.) +for (var method of BOTH) { + for (var value of [1e12, 1e240, Infinity]) { + assertThrowsInstanceOf(() => method(count, undefined, {length: value}), + Error); + } +} + +// argumentsList.length is converted to an integer. +for (var value of [1.7, "1", {valueOf() { return "1"; }}]) { + args = { + length: value, + "0": "ponies" + }; + for (var method of BOTH) { + var result = method(getArgs, undefined, args); + assertEq(result.length, 1); + assertEq(result[0], "ponies"); + } +} + +// If argumentsList.length is negative or NaN, no arguments are passed. +for (var method of BOTH) { + for (var num of [-1, -0.1, -0, -1e99, -Infinity, NaN]) { + assertEq(method(count, undefined, {length: num}).numArgsReceived, + 0); + } +} + +// Many arguments can be passed. +var many = 65537; +var args = {length: many, 0: "zero", [many - 1]: "last"}; +function testMany(...args) { + for (var i = 0; i < many; i++) { + assertEq(i in args, true); + assertEq(args[i], i === 0 ? "zero" : i === many - 1 ? "last" : undefined); + } + return this; +} +assertEq(Reflect.apply(testMany, "pass", args).toString(), "pass"); +assertEq(Reflect.construct(testMany, args) instanceof testMany, true); +assertEq(Reflect.apply(new Proxy(testMany, {}), "pass", args).toString(), "pass"); +assertEq(Reflect.construct(new Proxy(testMany, {}), args) instanceof testMany, true); + +reportCompare(0, 0); |