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