]>
Lady’s Gitweb - Pisces/blob - function.test.js
1 // ♓🌟 Piscēs ∷ function.test.js
2 // ====================================================================
4 // Copyright © 2022–2023 Lady [@ Lady’s Computer].
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
17 } from "./dev-deps.js";
24 createCallableFunction
,
25 createIllegalConstructor
,
26 createProxyConstructor
,
31 } from "./function.js";
33 describe("bind", () => {
34 it("[[Call]] binds this", () => {
47 it("[[Call]] binds arguments", () => {
51 return [this, ...args
];
55 ).call("failure", "cmfwyp"),
56 ["etaoin", "shrdlu", "cmfwyp"],
60 it("[[Call]] works with any arraylike third argument", () => {
64 return [this, ...args
];
72 ).call("failure", "cmfwyp"),
73 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
77 it("[[Construct]] throws an error", () => {
78 assertThrows(() => new bind(function () {}));
81 describe(".length", () => {
82 it("[[Get]] returns the correct length", () => {
83 assertStrictEquals(bind
.length
, 3);
87 describe(".name", () => {
88 it("[[Get]] returns the correct name", () => {
89 assertStrictEquals(bind
.name
, "bind");
94 describe("call", () => {
95 it("[[Call]] calls with the provided this value", () => {
108 it("[[Call]] calls with the provided arguments", () => {
112 return [this, ...args
];
115 ["shrdlu", "cmfwyp"],
117 ["etaoin", "shrdlu", "cmfwyp"],
121 it("[[Call]] works with any arraylike third argument", () => {
125 return [this, ...args
];
135 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
139 it("[[Construct]] throws an error", () => {
140 assertThrows(() => new call(function () {}, null, []));
143 describe(".length", () => {
144 it("[[Get]] returns the correct length", () => {
145 assertStrictEquals(call
.length
, 3);
149 describe(".name", () => {
150 it("[[Get]] returns the correct name", () => {
151 assertStrictEquals(call
.name
, "call");
156 describe("completesNormally", () => {
157 it("[[Call]] returns true for functions which complete normally", () => {
158 assertStrictEquals(completesNormally(() => {}), true);
161 it("[[Call]] returns false for functions which throw", () => {
163 completesNormally(() => {
170 it("[[Call]] throws when the argument is not callable", () => {
171 assertThrows(() => completesNormally(null));
174 it("[[Call]] throws when the argument is not provided", () => {
175 assertThrows(() => completesNormally());
178 it("[[Construct]] throws an error", () => {
179 assertThrows(() => new completesNormally(function () {}));
182 describe(".length", () => {
183 it("[[Get]] returns the correct length", () => {
184 assertStrictEquals(completesNormally
.length
, 1);
188 describe(".name", () => {
189 it("[[Get]] returns the correct name", () => {
190 assertStrictEquals(completesNormally
.name
, "completesNormally");
195 describe("construct", () => {
196 it("[[Call]] defaults to the constructor as the target", () => {
197 const constructor = class {};
199 Object
.getPrototypeOf(construct(
203 constructor.prototype,
207 it("[[Call]] constructs with the provided new target", () => {
208 const target = function () {};
221 it("[[Call]] constructs with the provided arguments", () => {
225 return [new.target
.value
, ...args
];
227 ["shrdlu", "cmfwyp"],
228 Object
.assign(function () {}, { value
: "etaoin" }),
230 ["etaoin", "shrdlu", "cmfwyp"],
234 it("[[Call]] works with any arraylike third argument", () => {
238 return [new.target
.value
, ...args
];
246 Object
.assign(function () {}, { value
: "etaoin" }),
248 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
252 it("[[Construct]] throws an error", () => {
253 assertThrows(() => new construct(function () {}, []));
256 describe(".length", () => {
257 it("[[Get]] returns the correct length", () => {
258 assertStrictEquals(construct
.length
, 2);
262 describe(".name", () => {
263 it("[[Get]] returns the correct name", () => {
264 assertStrictEquals(construct
.name
, "construct");
269 describe("createArrowFunction", () => {
270 it("[[Call]] sets this to undefined", () => {
281 it("[[Call]] transfers the provided arguments", () => {
285 return [this, ...args
];
287 ).call("failure", "etaoin", "shrdlu", "cmfwyp"),
288 [undefined, "etaoin", "shrdlu", "cmfwyp"],
292 it("[[Call]] correctly sets the length", () => {
295 function (_a
, _b
, _c
) {},
301 it("[[Call]] correctly sets the name", () => {
304 function etaoin() {},
310 it("[[Call]] allows the length to be overridden", () => {
313 function etaoin() {},
320 it("[[Call]] allows the name to be overridden", () => {
323 function etaoin() {},
330 it("[[Call]] returns an arrow function", () => {
331 assertThrows(() => new (createArrowFunction(function () {}))());
334 it("[[Call]] returns a function with no prototype property", () => {
337 createArrowFunction(function () {}, { prototype: {} })),
341 it("[[Construct]] throws an error", () => {
342 assertThrows(() => new createArrowFunction(function () {}));
345 describe(".length", () => {
346 it("[[Get]] returns the correct length", () => {
347 assertStrictEquals(createArrowFunction
.length
, 1);
351 describe(".name", () => {
352 it("[[Get]] returns the correct name", () => {
354 createArrowFunction
.name
,
355 "createArrowFunction",
361 describe("createCallableFunction", () => {
362 it("[[Call]] transfers the first argument to this", () => {
364 createCallableFunction(
368 ).call("fail", "pass"),
373 it("[[Call]] transfers the remaining arguments", () => {
375 createCallableFunction(
377 return [this, ...args
];
379 ).call("failure", "etaoin", "shrdlu", "cmfwyp"),
380 ["etaoin", "shrdlu", "cmfwyp"],
384 it("[[Call]] correctly sets the length", () => {
386 createCallableFunction(
387 function (_a
, _b
, _c
) {},
393 it("[[Call]] correctly sets the name", () => {
395 createCallableFunction(
396 function etaoin() {},
402 it("[[Call]] allows the length to be overridden", () => {
404 createCallableFunction(
405 function etaoin() {},
412 it("[[Call]] allows the name to be overridden", () => {
414 createCallableFunction(
415 function etaoin() {},
422 it("[[Call]] returns an arrow function", () => {
423 assertThrows(() => new (createCallableFunction(function () {}))());
426 it("[[Call]] returns a function with no prototype property", () => {
429 createCallableFunction(function () {}, { prototype: {} })),
433 it("[[Construct]] throws an error", () => {
434 assertThrows(() => new createCallableFunction(function () {}));
437 describe(".length", () => {
438 it("[[Get]] returns the correct length", () => {
439 assertStrictEquals(createCallableFunction
.length
, 1);
443 describe(".name", () => {
444 it("[[Get]] returns the correct name", () => {
446 createCallableFunction
.name
,
447 "createCallableFunction",
453 describe("createIllegalConstructor", () => {
454 it("[[Call]] returns a constructor", () => {
455 assert(isConstructor(createIllegalConstructor()));
458 it("[[Call]] works as expected when provided with no arguments", () => {
459 const constructor = createIllegalConstructor();
461 Object
.getPrototypeOf(constructor),
465 Object
.getPrototypeOf(constructor.prototype),
469 Object
.getOwnPropertyDescriptors(constructor.prototype),
472 constructor.prototype,
473 Object
.create(Object
.prototype, {
483 !Object
.getOwnPropertyDescriptor(constructor, "prototype")
486 assertStrictEquals(constructor.name
, "");
489 it("[[Call]] returns a correctly‐formed constructor when provided one argument", () => {
490 const constructorPrototype
= Object
.create(null, {
491 name
: { value
: "etaoin" },
492 length
: { value
: "3" },
493 prototype: { value
: {} },
495 const constructor = createIllegalConstructor(
496 Object
.create(constructorPrototype
),
498 assert(isConstructor(constructor));
500 Object
.getPrototypeOf(constructor),
501 constructorPrototype
,
503 assert(Object
.hasOwn(constructor, "prototype"));
505 constructor.prototype,
506 constructorPrototype
.prototype,
509 !Object
.getOwnPropertyDescriptor(constructor, "prototype")
512 assertStrictEquals(constructor.name
, "etaoin");
513 assertStrictEquals(constructor.length
, 3);
516 it("[[Call]] allows the length to be overridden", () => {
518 createIllegalConstructor(
519 function etaoin() {},
526 it("[[Call]] allows the name to be overridden", () => {
528 createIllegalConstructor(
529 function etaoin() {},
536 it("[[Call]] allows the prototype to be overridden", () => {
539 createIllegalConstructor(
540 function etaoin() {},
547 it("[[Construct]] throws an error", () => {
548 assertThrows(() => new createIllegalConstructor(function () {}));
551 describe(".length", () => {
552 it("[[Get]] returns the correct length", () => {
553 assertStrictEquals(createIllegalConstructor
.length
, 1);
557 describe(".name", () => {
558 it("[[Get]] returns the correct name", () => {
560 createIllegalConstructor
.name
,
561 "createIllegalConstructor",
566 describe("~", () => {
567 it("[[Call]] throws an error", () => {
569 createIllegalConstructor(function () {})();
573 it("[[Construct]] throws an error", () => {
575 createIllegalConstructor(function () {})();
581 describe("createProxyConstructor", () => {
582 it("[[Call]] returns a constructor", () => {
583 assert(isConstructor(createProxyConstructor({})));
586 it("[[Call]] throws with no arguments", () => {
587 assertThrows(() => createProxyConstructor());
590 it("[[Call]] throws if the second argument is not a constructor or undefined", () => {
591 assertThrows(() => createProxyConstructor({}, () => {}));
594 it("[[Call]] throws if the third argument is not a constructor or undefined", () => {
596 createProxyConstructor({}, undefined, () => {})
600 it("[[Call]] creates a proper proxy constructor", () => {
601 const constructorPrototype
= function etaoin(_
) {};
602 const constructor = class Constructor
603 extends constructorPrototype
{
604 constructor(_1
, _2
, _3
) {}
606 const proxyConstructor
= createProxyConstructor(
610 assert(isConstructor(proxyConstructor
));
612 Object
.getPrototypeOf(proxyConstructor
),
615 assertStrictEquals(proxyConstructor
.prototype, undefined);
616 assertStrictEquals(proxyConstructor
.name
, "ConstructorProxy");
617 assertStrictEquals(proxyConstructor
.length
, 3);
620 it("[[Call]] allows the length to be overridden", () => {
622 createProxyConstructor({}, undefined, undefined, {
629 it("[[Call]] allows the name to be overridden", () => {
631 createProxyConstructor({}, function etaoin() {}, undefined, {
638 it("[[Call]] does not allow the prototype to be overridden", () => {
640 createProxyConstructor({}, undefined, undefined, {
647 it("[[Construct]] throws an error", () => {
648 assertThrows(() => new createProxyConstructor({}));
651 describe(".length", () => {
652 it("[[Get]] returns the correct length", () => {
653 assertStrictEquals(createProxyConstructor
.length
, 2);
657 describe(".name", () => {
658 it("[[Get]] returns the correct name", () => {
660 createProxyConstructor
.name
,
661 "createProxyConstructor",
666 describe("~", () => {
667 it("[[Call]] throws an error", () => {
669 createProxyConstructor({})();
673 it("[[Construct]] produces a proxy", () => {
675 const proxyConstructor
= createProxyConstructor({
676 get(O
, P
, Receiver
) {
677 if (P
=== "etaoin") {
678 return Reflect
.get(O
, P
, Receiver
) ?? "success";
680 return Reflect
.get(O
, P
, Receiver
);
686 const proxy
= new proxyConstructor();
687 assertStrictEquals(proxy
.etaoin
, "success");
688 obj
.etaoin
= "shrdlu";
689 assertStrictEquals(proxy
.etaoin
, "shrdlu");
692 it("[[Construct]] receives the expected new.target", () => {
693 const constructor = function Constructor() {
694 return { name
: new.target
.name
};
697 new (createProxyConstructor({}, constructor))().name
,
701 new (createProxyConstructor(
704 function NewTarget() {},
711 describe("~length", () => {
712 it("[[GetOwnProperty]] has the correct descriptor", () => {
714 Object
.getOwnPropertyDescriptor(
715 createProxyConstructor({}),
728 describe("~name", () => {
729 it("[[GetOwnProperty]] has the correct descriptor", () => {
731 Object
.getOwnPropertyDescriptor(
732 createProxyConstructor({}),
738 value
: "ObjectProxy",
745 describe("~prototype", () => {
746 it("[[GetOwnProperty]] has the correct descriptor", () => {
748 Object
.getOwnPropertyDescriptor(
749 createProxyConstructor({}),
762 describe("~revocable", () => {
763 it("[[Call]] produces a revocable proxy", () => {
765 const proxyConstructor
= createProxyConstructor({
766 get(O
, P
, Receiver
) {
767 if (P
=== "etaoin") {
768 return Reflect
.get(O
, P
, Receiver
) ?? "success";
770 return Reflect
.get(O
, P
, Receiver
);
776 const { proxy
, revoke
} = proxyConstructor
.revocable();
777 assertStrictEquals(proxy
.etaoin
, "success");
778 obj
.etaoin
= "shrdlu";
779 assertStrictEquals(proxy
.etaoin
, "shrdlu");
781 assertThrows(() => proxy
.etaoin
);
784 it("[[Call]] receives the expected new.target", () => {
785 const constructor = function Constructor() {
786 return { name
: new.target
.name
};
789 createProxyConstructor({}, constructor).revocable().proxy
.name
,
793 createProxyConstructor(
796 function NewTarget() {},
797 ).revocable().proxy
.name
,
802 it("[[Construct]] throws an error", () => {
803 assertThrows(() => new (createProxyConstructor({})).revocable());
806 it("[[GetOwnProperty]] has the correct descriptor", () => {
807 const proxyConstructor
= createProxyConstructor({});
809 Object
.getOwnPropertyDescriptor(proxyConstructor
, "revocable"),
813 value
: proxyConstructor
.revocable
,
821 describe("identity", () => {
822 it("[[Call]] returns what it is given", () => {
824 assertStrictEquals(identity(value
), value
);
827 it("[[Construct]] is constructable", () => {
829 assertStrictEquals(new identity(value
), value
);
832 it("[[Construct]] is subclassable", () => {
834 assertStrictEquals(new class extends identity
{}(value
), value
);
837 describe(".length", () => {
838 it("[[Get]] returns the correct length", () => {
839 assertStrictEquals(identity
.length
, 1);
843 describe(".name", () => {
844 it("[[Get]] returns the correct name", () => {
845 assertStrictEquals(identity
.name
, "identity");
850 describe("isCallable", () => {
851 it("[[Call]] returns true for ordinary functions", () => {
852 assertStrictEquals(isCallable(function () {}), true);
855 it("[[Call]] returns true for arrow functions", () => {
856 assertStrictEquals(isCallable(() => {}), true);
859 it("[[Call]] returns true for generator functions", () => {
860 assertStrictEquals(isCallable(function* () {}), true);
863 it("[[Call]] returns true for classes", () => {
864 assertStrictEquals(isCallable(class {}), true);
867 it("[[Call]] returns true for builtin functions", () => {
868 assertStrictEquals(isCallable(Math
.ceil
), true);
871 it("[[Call]] returns true for getters", () => {
874 Object
.getOwnPropertyDescriptor({
884 it("[[Call]] returns true for setters", () => {
887 Object
.getOwnPropertyDescriptor({
897 it("[[Call]] returns false for null", () => {
898 assertStrictEquals(isCallable(null), false);
901 it("[[Call]] returns false for objects", () => {
902 assertStrictEquals(isCallable({}), false);
905 it("[[Construct]] throws an error", () => {
906 assertThrows(() => new isCallable(function () {}));
909 describe(".length", () => {
910 it("[[Get]] returns the correct length", () => {
911 assertStrictEquals(isCallable
.length
, 1);
915 describe(".name", () => {
916 it("[[Get]] returns the correct name", () => {
917 assertStrictEquals(isCallable
.name
, "isCallable");
922 describe("isConstructor", () => {
923 it("[[Call]] returns true for ordinary functions", () => {
924 assertStrictEquals(isConstructor(function () {}), true);
927 it("[[Call]] returns false for arrow functions", () => {
928 assertStrictEquals(isConstructor(() => {}), false);
931 it("[[Call]] returns false for generator functions", () => {
932 assertStrictEquals(isConstructor(function* () {}), false);
935 it("[[Call]] returns true for classes", () => {
936 assertStrictEquals(isConstructor(class {}), true);
939 it("[[Call]] returns false for builtin functions", () => {
940 assertStrictEquals(isConstructor(Math
.ceil
), false);
943 it("[[Call]] returns false for getters", () => {
946 Object
.getOwnPropertyDescriptor({
956 it("[[Call]] returns false for setters", () => {
959 Object
.getOwnPropertyDescriptor({
969 it("[[Call]] returns false for null", () => {
970 assertStrictEquals(isConstructor(null), false);
973 it("[[Call]] returns false for objects", () => {
974 assertStrictEquals(isConstructor({}), false);
977 it("[[Construct]] throws an error", () => {
978 assertThrows(() => new isConstructor(function () {}));
981 describe(".length", () => {
982 it("[[Get]] returns the correct length", () => {
983 assertStrictEquals(isConstructor
.length
, 1);
987 describe(".name", () => {
988 it("[[Get]] returns the correct name", () => {
989 assertStrictEquals(isConstructor
.name
, "isConstructor");
994 describe("ordinaryHasInstance", () => {
995 it("[[Call]] walks the prototype chain", () => {
996 const constructor = class {
997 [Symbol
.hasInstance
]() {
1002 ordinaryHasInstance(
1004 new class extends constructor {}(),
1010 it("[[Construct]] throws an error", () => {
1011 assertThrows(() => new ordinaryHasInstance(function () {}, {}));
1014 describe(".length", () => {
1015 it("[[Get]] returns the correct length", () => {
1016 assertStrictEquals(ordinaryHasInstance
.length
, 2);
1020 describe(".name", () => {
1021 it("[[Get]] returns the correct name", () => {
1023 ordinaryHasInstance
.name
,
1024 "ordinaryHasInstance",
This page took 0.173501 seconds and 5 git commands to generate.