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