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