]> Lady’s Gitweb - Pisces/blob - function.test.js
Minor refactors to numeric.js
[Pisces] / function.test.js
1 // SPDX-FileCopyrightText: 2022, 2023, 2025 Lady <https://www.ladys.computer/about/#lady>
2 // SPDX-License-Identifier: MPL-2.0
3 /**
4 * ⁌ ♓🧩 Piscēs ∷ function.test.js
5 *
6 * Copyright © 2022–2023, 2025 Lady [@ Ladys Computer].
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
11 */
12
13 import {
14 assert,
15 assertEquals,
16 assertNotStrictEquals,
17 assertSpyCall,
18 assertSpyCalls,
19 assertStrictEquals,
20 assertThrows,
21 describe,
22 it,
23 spy,
24 } from "./dev-deps.js";
25 import {
26 bind,
27 call,
28 completesNormally,
29 construct,
30 createArrowFunction,
31 createCallableFunction,
32 createIllegalConstructor,
33 createProxyConstructor,
34 identity,
35 isCallable,
36 isConstructor,
37 maybe,
38 ordinaryHasInstance,
39 } from "./function.js";
40
41 describe("bind", () => {
42 it("[[Call]] binds this", () => {
43 assertStrictEquals(
44 bind(
45 function () {
46 return this;
47 },
48 "pass",
49 [],
50 ).call("fail"),
51 "pass",
52 );
53 });
54
55 it("[[Call]] binds arguments", () => {
56 assertEquals(
57 bind(
58 function (...args) {
59 return [this, ...args];
60 },
61 "etaoin",
62 ["shrdlu"],
63 ).call("failure", "cmfwyp"),
64 ["etaoin", "shrdlu", "cmfwyp"],
65 );
66 });
67
68 it("[[Call]] works with any arraylike third argument", () => {
69 assertEquals(
70 bind(
71 function (...args) {
72 return [this, ...args];
73 },
74 "etaoin",
75 {
76 1: "shrdlu",
77 3: "failure",
78 length: 3,
79 },
80 ).call("failure", "cmfwyp"),
81 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
82 );
83 });
84
85 it("[[Construct]] throws an error", () => {
86 assertThrows(() => new bind(function () {}));
87 });
88
89 describe(".length", () => {
90 it("[[Get]] returns the correct length", () => {
91 assertStrictEquals(bind.length, 3);
92 });
93 });
94
95 describe(".name", () => {
96 it("[[Get]] returns the correct name", () => {
97 assertStrictEquals(bind.name, "bind");
98 });
99 });
100 });
101
102 describe("call", () => {
103 it("[[Call]] calls with the provided this value", () => {
104 assertStrictEquals(
105 call(
106 function () {
107 return this;
108 },
109 "pass",
110 [],
111 ),
112 "pass",
113 );
114 });
115
116 it("[[Call]] calls with the provided arguments", () => {
117 assertEquals(
118 call(
119 function (...args) {
120 return [this, ...args];
121 },
122 "etaoin",
123 ["shrdlu", "cmfwyp"],
124 ),
125 ["etaoin", "shrdlu", "cmfwyp"],
126 );
127 });
128
129 it("[[Call]] works with any arraylike third argument", () => {
130 assertEquals(
131 call(
132 function (...args) {
133 return [this, ...args];
134 },
135 "etaoin",
136 {
137 1: "shrdlu",
138 3: "cmfwyp",
139 4: "failure",
140 length: 4,
141 },
142 ),
143 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
144 );
145 });
146
147 it("[[Construct]] throws an error", () => {
148 assertThrows(() => new call(function () {}, null, []));
149 });
150
151 describe(".length", () => {
152 it("[[Get]] returns the correct length", () => {
153 assertStrictEquals(call.length, 3);
154 });
155 });
156
157 describe(".name", () => {
158 it("[[Get]] returns the correct name", () => {
159 assertStrictEquals(call.name, "call");
160 });
161 });
162 });
163
164 describe("completesNormally", () => {
165 it("[[Call]] returns true for functions which complete normally", () => {
166 assertStrictEquals(completesNormally(() => {}), true);
167 });
168
169 it("[[Call]] returns false for functions which throw", () => {
170 assertStrictEquals(
171 completesNormally(() => {
172 throw null;
173 }),
174 false,
175 );
176 });
177
178 it("[[Call]] throws when the argument is not callable", () => {
179 assertThrows(() => completesNormally(null));
180 });
181
182 it("[[Call]] throws when the argument is not provided", () => {
183 assertThrows(() => completesNormally());
184 });
185
186 it("[[Construct]] throws an error", () => {
187 assertThrows(() => new completesNormally(function () {}));
188 });
189
190 describe(".length", () => {
191 it("[[Get]] returns the correct length", () => {
192 assertStrictEquals(completesNormally.length, 1);
193 });
194 });
195
196 describe(".name", () => {
197 it("[[Get]] returns the correct name", () => {
198 assertStrictEquals(completesNormally.name, "completesNormally");
199 });
200 });
201 });
202
203 describe("construct", () => {
204 it("[[Call]] defaults to the constructor as the target", () => {
205 const constructor = class {};
206 assertStrictEquals(
207 Object.getPrototypeOf(construct(
208 constructor,
209 [],
210 )),
211 constructor.prototype,
212 );
213 });
214
215 it("[[Call]] constructs with the provided new target", () => {
216 const target = function () {};
217 assertStrictEquals(
218 construct(
219 function () {
220 return new.target;
221 },
222 [],
223 target,
224 ),
225 target,
226 );
227 });
228
229 it("[[Call]] constructs with the provided arguments", () => {
230 assertEquals(
231 construct(
232 function (...args) {
233 return [new.target.value, ...args];
234 },
235 ["shrdlu", "cmfwyp"],
236 Object.assign(function () {}, { value: "etaoin" }),
237 ),
238 ["etaoin", "shrdlu", "cmfwyp"],
239 );
240 });
241
242 it("[[Call]] works with any arraylike third argument", () => {
243 assertEquals(
244 construct(
245 function (...args) {
246 return [new.target.value, ...args];
247 },
248 {
249 1: "shrdlu",
250 3: "cmfwyp",
251 4: "failure",
252 length: 4,
253 },
254 Object.assign(function () {}, { value: "etaoin" }),
255 ),
256 ["etaoin", undefined, "shrdlu", undefined, "cmfwyp"],
257 );
258 });
259
260 it("[[Construct]] throws an error", () => {
261 assertThrows(() => new construct(function () {}, []));
262 });
263
264 describe(".length", () => {
265 it("[[Get]] returns the correct length", () => {
266 assertStrictEquals(construct.length, 2);
267 });
268 });
269
270 describe(".name", () => {
271 it("[[Get]] returns the correct name", () => {
272 assertStrictEquals(construct.name, "construct");
273 });
274 });
275 });
276
277 describe("createArrowFunction", () => {
278 it("[[Call]] sets this to undefined", () => {
279 assertStrictEquals(
280 createArrowFunction(
281 function () {
282 return this;
283 },
284 ).call("fail"),
285 undefined,
286 );
287 });
288
289 it("[[Call]] transfers the provided arguments", () => {
290 assertEquals(
291 createArrowFunction(
292 function (...args) {
293 return [this, ...args];
294 },
295 ).call("failure", "etaoin", "shrdlu", "cmfwyp"),
296 [undefined, "etaoin", "shrdlu", "cmfwyp"],
297 );
298 });
299
300 it("[[Call]] correctly sets the length", () => {
301 assertStrictEquals(
302 createArrowFunction(
303 function (_a, _b, _c) {},
304 ).length,
305 3,
306 );
307 });
308
309 it("[[Call]] correctly sets the name", () => {
310 assertStrictEquals(
311 createArrowFunction(
312 function etaoin() {},
313 ).name,
314 "etaoin",
315 );
316 });
317
318 it("[[Call]] allows the length to be overridden", () => {
319 assertStrictEquals(
320 createArrowFunction(
321 function etaoin() {},
322 { length: 100 },
323 ).length,
324 100,
325 );
326 });
327
328 it("[[Call]] allows the name to be overridden", () => {
329 assertStrictEquals(
330 createArrowFunction(
331 function etaoin() {},
332 { name: "shrdlu" },
333 ).name,
334 "shrdlu",
335 );
336 });
337
338 it("[[Call]] returns an arrow function", () => {
339 assertThrows(() => new (createArrowFunction(function () {}))());
340 });
341
342 it("[[Call]] returns a function with no prototype property", () => {
343 assert(
344 !("prototype"
345 in createArrowFunction(function () {}, { prototype: {} })),
346 );
347 });
348
349 it("[[Construct]] throws an error", () => {
350 assertThrows(() => new createArrowFunction(function () {}));
351 });
352
353 describe(".length", () => {
354 it("[[Get]] returns the correct length", () => {
355 assertStrictEquals(createArrowFunction.length, 1);
356 });
357 });
358
359 describe(".name", () => {
360 it("[[Get]] returns the correct name", () => {
361 assertStrictEquals(
362 createArrowFunction.name,
363 "createArrowFunction",
364 );
365 });
366 });
367 });
368
369 describe("createCallableFunction", () => {
370 it("[[Call]] transfers the first argument to this", () => {
371 assertStrictEquals(
372 createCallableFunction(
373 function () {
374 return this;
375 },
376 ).call("fail", "pass"),
377 "pass",
378 );
379 });
380
381 it("[[Call]] transfers the remaining arguments", () => {
382 assertEquals(
383 createCallableFunction(
384 function (...args) {
385 return [this, ...args];
386 },
387 ).call("failure", "etaoin", "shrdlu", "cmfwyp"),
388 ["etaoin", "shrdlu", "cmfwyp"],
389 );
390 });
391
392 it("[[Call]] correctly sets the length", () => {
393 assertStrictEquals(
394 createCallableFunction(
395 function (_a, _b, _c) {},
396 ).length,
397 4,
398 );
399 });
400
401 it("[[Call]] correctly sets the name", () => {
402 assertStrictEquals(
403 createCallableFunction(
404 function etaoin() {},
405 ).name,
406 "etaoin",
407 );
408 });
409
410 it("[[Call]] allows the length to be overridden", () => {
411 assertStrictEquals(
412 createCallableFunction(
413 function etaoin() {},
414 { length: 100 },
415 ).length,
416 100,
417 );
418 });
419
420 it("[[Call]] allows the name to be overridden", () => {
421 assertStrictEquals(
422 createCallableFunction(
423 function etaoin() {},
424 { name: "shrdlu" },
425 ).name,
426 "shrdlu",
427 );
428 });
429
430 it("[[Call]] returns an arrow function", () => {
431 assertThrows(() => new (createCallableFunction(function () {}))());
432 });
433
434 it("[[Call]] returns a function with no prototype property", () => {
435 assert(
436 !("prototype"
437 in createCallableFunction(function () {}, { prototype: {} })),
438 );
439 });
440
441 it("[[Construct]] throws an error", () => {
442 assertThrows(() => new createCallableFunction(function () {}));
443 });
444
445 describe(".length", () => {
446 it("[[Get]] returns the correct length", () => {
447 assertStrictEquals(createCallableFunction.length, 1);
448 });
449 });
450
451 describe(".name", () => {
452 it("[[Get]] returns the correct name", () => {
453 assertStrictEquals(
454 createCallableFunction.name,
455 "createCallableFunction",
456 );
457 });
458 });
459 });
460
461 describe("createIllegalConstructor", () => {
462 it("[[Call]] returns a constructor", () => {
463 assert(isConstructor(createIllegalConstructor()));
464 });
465
466 it("[[Call]] works as expected when provided with no arguments", () => {
467 const constructor = createIllegalConstructor();
468 assertStrictEquals(
469 Object.getPrototypeOf(constructor),
470 Function.prototype,
471 );
472 assertStrictEquals(
473 Object.getPrototypeOf(constructor.prototype),
474 Object.prototype,
475 );
476 assertEquals(
477 constructor.prototype,
478 Object.create(Object.prototype, {
479 constructor: {
480 configurable: true,
481 enumerable: false,
482 value: constructor,
483 writable: true,
484 },
485 }),
486 );
487 assert(
488 !Object.getOwnPropertyDescriptor(constructor, "prototype")
489 .writable,
490 );
491 assertStrictEquals(constructor.name, "");
492 });
493
494 it("[[Call]] returns a correctly‐formed constructor when provided one argument", () => {
495 const constructorPrototype = Object.create(null, {
496 name: { value: "etaoin" },
497 length: { value: "3" },
498 prototype: { value: {} },
499 });
500 const constructor = createIllegalConstructor(
501 Object.create(constructorPrototype),
502 );
503 assert(isConstructor(constructor));
504 assertStrictEquals(
505 Object.getPrototypeOf(constructor),
506 constructorPrototype,
507 );
508 assert(Object.hasOwn(constructor, "prototype"));
509 assertStrictEquals(
510 constructor.prototype,
511 constructorPrototype.prototype,
512 );
513 assert(
514 !Object.getOwnPropertyDescriptor(constructor, "prototype")
515 .writable,
516 );
517 assertStrictEquals(constructor.name, "etaoin");
518 assertStrictEquals(constructor.length, 3);
519 });
520
521 it("[[Call]] allows the length to be overridden", () => {
522 assertStrictEquals(
523 createIllegalConstructor(
524 function etaoin() {},
525 { length: 100 },
526 ).length,
527 100,
528 );
529 });
530
531 it("[[Call]] allows the name to be overridden", () => {
532 assertStrictEquals(
533 createIllegalConstructor(
534 function etaoin() {},
535 { name: "shrdlu" },
536 ).name,
537 "shrdlu",
538 );
539 });
540
541 it("[[Call]] allows the prototype to be overridden", () => {
542 const obj = {};
543 assertStrictEquals(
544 createIllegalConstructor(
545 function etaoin() {},
546 { prototype: obj },
547 ).prototype,
548 obj,
549 );
550 });
551
552 it("[[Construct]] throws an error", () => {
553 assertThrows(() => new createIllegalConstructor(function () {}));
554 });
555
556 describe(".length", () => {
557 it("[[Get]] returns the correct length", () => {
558 assertStrictEquals(createIllegalConstructor.length, 1);
559 });
560 });
561
562 describe(".name", () => {
563 it("[[Get]] returns the correct name", () => {
564 assertStrictEquals(
565 createIllegalConstructor.name,
566 "createIllegalConstructor",
567 );
568 });
569 });
570
571 describe("~", () => {
572 it("[[Call]] throws an error", () => {
573 assertThrows(() => {
574 createIllegalConstructor(function () {})();
575 });
576 });
577
578 it("[[Construct]] throws an error", () => {
579 assertThrows(() => {
580 createIllegalConstructor(function () {})();
581 });
582 });
583 });
584 });
585
586 describe("createProxyConstructor", () => {
587 it("[[Call]] returns a constructor", () => {
588 assert(isConstructor(createProxyConstructor({})));
589 });
590
591 it("[[Call]] throws with no arguments", () => {
592 assertThrows(() => createProxyConstructor());
593 });
594
595 it("[[Call]] throws if the second argument is not a constructor or undefined", () => {
596 assertThrows(() => createProxyConstructor({}, () => {}));
597 });
598
599 it("[[Call]] throws if the third argument is not a constructor or undefined", () => {
600 assertThrows(() =>
601 createProxyConstructor({}, undefined, () => {})
602 );
603 });
604
605 it("[[Call]] creates a proper proxy constructor", () => {
606 const constructorPrototype = function etaoin(_) {};
607 const constructor = class Constructor
608 extends constructorPrototype {
609 constructor(_1, _2, _3) {}
610 };
611 const proxyConstructor = createProxyConstructor(
612 {},
613 constructor,
614 );
615 assert(isConstructor(proxyConstructor));
616 assertStrictEquals(
617 Object.getPrototypeOf(proxyConstructor),
618 Proxy,
619 );
620 assertStrictEquals(proxyConstructor.prototype, undefined);
621 assertStrictEquals(proxyConstructor.name, "ConstructorProxy");
622 assertStrictEquals(proxyConstructor.length, 3);
623 });
624
625 it("[[Call]] allows the length to be overridden", () => {
626 assertStrictEquals(
627 createProxyConstructor({}, undefined, undefined, {
628 length: 100,
629 }).length,
630 100,
631 );
632 });
633
634 it("[[Call]] allows the name to be overridden", () => {
635 assertStrictEquals(
636 createProxyConstructor({}, function etaoin() {}, undefined, {
637 name: "shrdlu",
638 }).name,
639 "shrdlu",
640 );
641 });
642
643 it("[[Call]] does not allow the prototype to be overridden", () => {
644 assertStrictEquals(
645 createProxyConstructor({}, undefined, undefined, {
646 prototype: {},
647 }).prototype,
648 undefined,
649 );
650 });
651
652 it("[[Construct]] throws an error", () => {
653 assertThrows(() => new createProxyConstructor({}));
654 });
655
656 describe(".length", () => {
657 it("[[Get]] returns the correct length", () => {
658 assertStrictEquals(createProxyConstructor.length, 2);
659 });
660 });
661
662 describe(".name", () => {
663 it("[[Get]] returns the correct name", () => {
664 assertStrictEquals(
665 createProxyConstructor.name,
666 "createProxyConstructor",
667 );
668 });
669 });
670
671 describe("~", () => {
672 it("[[Call]] throws an error", () => {
673 assertThrows(() => {
674 createProxyConstructor({})();
675 });
676 });
677
678 it("[[Construct]] produces a proxy", () => {
679 const obj = {};
680 const proxyConstructor = createProxyConstructor({
681 get(O, P, Receiver) {
682 if (P === "etaoin") {
683 return Reflect.get(O, P, Receiver) ?? "success";
684 } else {
685 return Reflect.get(O, P, Receiver);
686 }
687 },
688 }, function () {
689 return obj;
690 });
691 const proxy = new proxyConstructor();
692 assertStrictEquals(proxy.etaoin, "success");
693 obj.etaoin = "shrdlu";
694 assertStrictEquals(proxy.etaoin, "shrdlu");
695 });
696
697 it("[[Construct]] receives the expected new.target", () => {
698 const constructor = function Constructor() {
699 return { name: new.target.name };
700 };
701 assertStrictEquals(
702 new (createProxyConstructor({}, constructor))().name,
703 "Constructor",
704 );
705 assertStrictEquals(
706 new (createProxyConstructor(
707 {},
708 constructor,
709 function NewTarget() {},
710 ))().name,
711 "NewTarget",
712 );
713 });
714 });
715
716 describe("~is[[.name]]", () => {
717 it("[[GetOwnProperty]] defines the appropriate method", () => {
718 assertNotStrictEquals(
719 Object.getOwnPropertyDescriptor(
720 createProxyConstructor({}),
721 "isProxy",
722 ),
723 undefined,
724 );
725 assertNotStrictEquals(
726 Object.getOwnPropertyDescriptor(
727 createProxyConstructor({}, function Base() {}),
728 "isBaseProxy",
729 ),
730 undefined,
731 );
732 assertNotStrictEquals(
733 Object.getOwnPropertyDescriptor(
734 createProxyConstructor({}, function Bad() {}, undefined, {
735 name: "⸺",
736 }),
737 "is⸺",
738 ),
739 undefined,
740 );
741 });
742
743 it("[[GetOwnProperty]] has the correct descriptor", () => {
744 const proxyConstructor = createProxyConstructor({});
745 assertEquals(
746 Object.getOwnPropertyDescriptor(
747 proxyConstructor,
748 "isProxy",
749 ),
750 {
751 configurable: true,
752 enumerable: false,
753 value: proxyConstructor.isProxy,
754 writable: true,
755 },
756 );
757 });
758
759 it("[[Call]] returns true for created proxies", () => {
760 const proxyConstructor = createProxyConstructor({});
761 const proxy = new proxyConstructor();
762 assertStrictEquals(
763 proxyConstructor.isProxy(proxy),
764 true,
765 );
766 });
767
768 it("[[Call]] returns false for nonproxies", () => {
769 const constructor = function Base() {};
770 const proxyConstructor = createProxyConstructor({}, constructor);
771 assertStrictEquals(
772 proxyConstructor.isBaseProxy(new constructor()),
773 false,
774 );
775 });
776
777 it("[[Construct]] throws an error", () => {
778 const proxyConstructor = createProxyConstructor({});
779 assertThrows(() => new proxyConstructor.isProxy({}));
780 });
781
782 describe(".length", () => {
783 it("[[Get]] returns the correct length", () => {
784 const proxyConstructor = createProxyConstructor({});
785 assertStrictEquals(proxyConstructor.isProxy.length, 1);
786 });
787 });
788
789 describe(".name", () => {
790 it("[[Get]] returns the correct name", () => {
791 const proxyConstructor = createProxyConstructor({});
792 assertStrictEquals(proxyConstructor.isProxy.name, "isProxy");
793 const otherProxyConstructor = createProxyConstructor(
794 {},
795 function Base() {},
796 );
797 assertStrictEquals(
798 otherProxyConstructor.isBaseProxy.name,
799 "isBaseProxy",
800 );
801 });
802 });
803 });
804
805 describe("~length", () => {
806 it("[[GetOwnProperty]] has the correct descriptor", () => {
807 assertEquals(
808 Object.getOwnPropertyDescriptor(
809 createProxyConstructor({}),
810 "length",
811 ),
812 {
813 configurable: true,
814 enumerable: false,
815 value: 1,
816 writable: false,
817 },
818 );
819 });
820 });
821
822 describe("~name", () => {
823 it("[[GetOwnProperty]] has the correct descriptor", () => {
824 assertEquals(
825 Object.getOwnPropertyDescriptor(
826 createProxyConstructor({}),
827 "name",
828 ),
829 {
830 configurable: true,
831 enumerable: false,
832 value: "Proxy",
833 writable: false,
834 },
835 );
836 });
837 });
838
839 describe("~prototype", () => {
840 it("[[GetOwnProperty]] has the correct descriptor", () => {
841 assertEquals(
842 Object.getOwnPropertyDescriptor(
843 createProxyConstructor({}),
844 "prototype",
845 ),
846 {
847 configurable: false,
848 enumerable: false,
849 value: undefined,
850 writable: false,
851 },
852 );
853 });
854 });
855
856 describe("~revocable", () => {
857 it("[[Call]] produces a revocable proxy", () => {
858 const obj = {};
859 const proxyConstructor = createProxyConstructor({
860 get(O, P, Receiver) {
861 if (P === "etaoin") {
862 return Reflect.get(O, P, Receiver) ?? "success";
863 } else {
864 return Reflect.get(O, P, Receiver);
865 }
866 },
867 }, function () {
868 return obj;
869 });
870 const { proxy, revoke } = proxyConstructor.revocable();
871 assertStrictEquals(proxy.etaoin, "success");
872 obj.etaoin = "shrdlu";
873 assertStrictEquals(proxy.etaoin, "shrdlu");
874 revoke();
875 assertThrows(() => proxy.etaoin);
876 });
877
878 it("[[Call]] receives the expected new.target", () => {
879 const constructor = function Constructor() {
880 return { name: new.target.name };
881 };
882 assertStrictEquals(
883 createProxyConstructor({}, constructor).revocable().proxy.name,
884 "Constructor",
885 );
886 assertStrictEquals(
887 createProxyConstructor(
888 {},
889 constructor,
890 function NewTarget() {},
891 ).revocable().proxy.name,
892 "NewTarget",
893 );
894 });
895
896 it("[[Construct]] throws an error", () => {
897 assertThrows(() => new (createProxyConstructor({})).revocable());
898 });
899
900 it("[[GetOwnProperty]] has the correct descriptor", () => {
901 const proxyConstructor = createProxyConstructor({});
902 assertEquals(
903 Object.getOwnPropertyDescriptor(proxyConstructor, "revocable"),
904 {
905 configurable: true,
906 enumerable: false,
907 value: proxyConstructor.revocable,
908 writable: true,
909 },
910 );
911 });
912 });
913 });
914
915 describe("identity", () => {
916 it("[[Call]] returns what it is given", () => {
917 const value = {};
918 assertStrictEquals(identity(value), value);
919 });
920
921 it("[[Construct]] is constructable", () => {
922 const value = {};
923 assertStrictEquals(new identity(value), value);
924 });
925
926 it("[[Construct]] is subclassable", () => {
927 const value = {};
928 assertStrictEquals(new class extends identity {}(value), value);
929 });
930
931 describe(".length", () => {
932 it("[[Get]] returns the correct length", () => {
933 assertStrictEquals(identity.length, 1);
934 });
935 });
936
937 describe(".name", () => {
938 it("[[Get]] returns the correct name", () => {
939 assertStrictEquals(identity.name, "identity");
940 });
941 });
942 });
943
944 describe("isCallable", () => {
945 it("[[Call]] returns true for ordinary functions", () => {
946 assertStrictEquals(isCallable(function () {}), true);
947 });
948
949 it("[[Call]] returns true for arrow functions", () => {
950 assertStrictEquals(isCallable(() => {}), true);
951 });
952
953 it("[[Call]] returns true for generator functions", () => {
954 assertStrictEquals(isCallable(function* () {}), true);
955 });
956
957 it("[[Call]] returns true for classes", () => {
958 assertStrictEquals(isCallable(class {}), true);
959 });
960
961 it("[[Call]] returns true for builtin functions", () => {
962 assertStrictEquals(isCallable(Math.ceil), true);
963 });
964
965 it("[[Call]] returns true for getters", () => {
966 assertStrictEquals(
967 isCallable(
968 Object.getOwnPropertyDescriptor({
969 get foo() {
970 return undefined;
971 },
972 }, "foo").get,
973 ),
974 true,
975 );
976 });
977
978 it("[[Call]] returns true for setters", () => {
979 assertStrictEquals(
980 isCallable(
981 Object.getOwnPropertyDescriptor({
982 set foo($) {
983 /* do nothing */
984 },
985 }, "foo").set,
986 ),
987 true,
988 );
989 });
990
991 it("[[Call]] returns false for null", () => {
992 assertStrictEquals(isCallable(null), false);
993 });
994
995 it("[[Call]] returns false for objects", () => {
996 assertStrictEquals(isCallable({}), false);
997 });
998
999 it("[[Construct]] throws an error", () => {
1000 assertThrows(() => new isCallable(function () {}));
1001 });
1002
1003 describe(".length", () => {
1004 it("[[Get]] returns the correct length", () => {
1005 assertStrictEquals(isCallable.length, 1);
1006 });
1007 });
1008
1009 describe(".name", () => {
1010 it("[[Get]] returns the correct name", () => {
1011 assertStrictEquals(isCallable.name, "isCallable");
1012 });
1013 });
1014 });
1015
1016 describe("isConstructor", () => {
1017 it("[[Call]] returns true for ordinary functions", () => {
1018 assertStrictEquals(isConstructor(function () {}), true);
1019 });
1020
1021 it("[[Call]] returns false for arrow functions", () => {
1022 assertStrictEquals(isConstructor(() => {}), false);
1023 });
1024
1025 it("[[Call]] returns false for generator functions", () => {
1026 assertStrictEquals(isConstructor(function* () {}), false);
1027 });
1028
1029 it("[[Call]] returns true for classes", () => {
1030 assertStrictEquals(isConstructor(class {}), true);
1031 });
1032
1033 it("[[Call]] returns false for builtin functions", () => {
1034 assertStrictEquals(isConstructor(Math.ceil), false);
1035 });
1036
1037 it("[[Call]] returns false for getters", () => {
1038 assertStrictEquals(
1039 isConstructor(
1040 Object.getOwnPropertyDescriptor({
1041 get foo() {
1042 return undefined;
1043 },
1044 }, "foo").get,
1045 ),
1046 false,
1047 );
1048 });
1049
1050 it("[[Call]] returns false for setters", () => {
1051 assertStrictEquals(
1052 isConstructor(
1053 Object.getOwnPropertyDescriptor({
1054 set foo($) {
1055 /* do nothing */
1056 },
1057 }, "foo").set,
1058 ),
1059 false,
1060 );
1061 });
1062
1063 it("[[Call]] returns false for null", () => {
1064 assertStrictEquals(isConstructor(null), false);
1065 });
1066
1067 it("[[Call]] returns false for objects", () => {
1068 assertStrictEquals(isConstructor({}), false);
1069 });
1070
1071 it("[[Construct]] throws an error", () => {
1072 assertThrows(() => new isConstructor(function () {}));
1073 });
1074
1075 describe(".length", () => {
1076 it("[[Get]] returns the correct length", () => {
1077 assertStrictEquals(isConstructor.length, 1);
1078 });
1079 });
1080
1081 describe(".name", () => {
1082 it("[[Get]] returns the correct name", () => {
1083 assertStrictEquals(isConstructor.name, "isConstructor");
1084 });
1085 });
1086 });
1087
1088 describe("maybe", () => {
1089 it("[[Call]] calls if not nullish", () => {
1090 const wrapper = spy(() => "success");
1091 assertStrictEquals(maybe(0, wrapper), "success");
1092 assertSpyCalls(wrapper, 1);
1093 assertSpyCall(wrapper, 0, {
1094 args: [0],
1095 self: undefined,
1096 returned: "success",
1097 });
1098 });
1099
1100 it("[[Call]] does not call if nullish", () => {
1101 const wrapper = spy(() => "success");
1102 assertStrictEquals(maybe(null, wrapper), null);
1103 assertStrictEquals(maybe(undefined, wrapper), undefined);
1104 assertSpyCalls(wrapper, 0);
1105 });
1106
1107 it("[[Construct]] throws an error", () => {
1108 assertThrows(() => new maybe(true, ($) => $));
1109 });
1110
1111 describe(".length", () => {
1112 it("[[Get]] returns the correct length", () => {
1113 assertStrictEquals(maybe.length, 2);
1114 });
1115 });
1116
1117 describe(".name", () => {
1118 it("[[Get]] returns the correct name", () => {
1119 assertStrictEquals(maybe.name, "maybe");
1120 });
1121 });
1122 });
1123
1124 describe("ordinaryHasInstance", () => {
1125 it("[[Call]] walks the prototype chain", () => {
1126 const constructor = class {
1127 [Symbol.hasInstance]() {
1128 return false;
1129 }
1130 };
1131 assertStrictEquals(
1132 ordinaryHasInstance(
1133 constructor,
1134 new class extends constructor {}(),
1135 ),
1136 true,
1137 );
1138 });
1139
1140 it("[[Construct]] throws an error", () => {
1141 assertThrows(() => new ordinaryHasInstance(function () {}, {}));
1142 });
1143
1144 describe(".length", () => {
1145 it("[[Get]] returns the correct length", () => {
1146 assertStrictEquals(ordinaryHasInstance.length, 2);
1147 });
1148 });
1149
1150 describe(".name", () => {
1151 it("[[Get]] returns the correct name", () => {
1152 assertStrictEquals(
1153 ordinaryHasInstance.name,
1154 "ordinaryHasInstance",
1155 );
1156 });
1157 });
1158 });
This page took 0.901269 seconds and 5 git commands to generate.