summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Reflect/argumentsList.js
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--js/src/tests/non262/Reflect/argumentsList.js164
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);