]> Lady’s Gitweb - Pisces/blob - object.test.js
Improve object.js a·p·i
[Pisces] / object.test.js
1 // ♓🌟 Piscēs ∷ object.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 defineOwnProperties,
23 defineOwnProperty,
24 deleteOwnProperty,
25 freeze,
26 frozenCopy,
27 getMethod,
28 getOwnPropertyDescriptor,
29 getOwnPropertyDescriptors,
30 getOwnPropertyKeys,
31 getOwnPropertyStrings,
32 getOwnPropertySymbols,
33 getPropertyValue,
34 getPrototype,
35 hasOwnProperty,
36 hasProperty,
37 isExtensibleObject,
38 isUnfrozenObject,
39 isUnsealedObject,
40 LazyLoader,
41 namedEntries,
42 namedKeys,
43 namedValues,
44 objectCreate,
45 objectFromEntries,
46 preventExtensions,
47 PropertyDescriptor,
48 seal,
49 setPropertyValue,
50 setPropertyValues,
51 setPrototype,
52 toObject,
53 toPropertyKey,
54 } from "./object.js";
55
56 describe("LazyLoader", () => {
57 const symbol = Symbol("foo");
58 const prototype = {};
59 const etaoinMethod = spy(() => "success");
60 const shrdluMethod = spy(() => "success");
61 const cmfwypMethod = spy(() => "success");
62 const vbgkqjMethod = spy(() => "success");
63 const methodsObject = Object.create(
64 prototype,
65 {
66 etaoin: {
67 configurable: false,
68 enumerable: true,
69 value: etaoinMethod,
70 writable: false,
71 },
72 shrdlu: {
73 configurable: true,
74 enumerable: false,
75 value: shrdluMethod,
76 writable: false,
77 },
78 cmfwyp: {
79 configurable: true,
80 enumerable: false,
81 get() {
82 return cmfwypMethod;
83 },
84 },
85 vbgkqj: {
86 configurable: false,
87 enumerable: true,
88 get() {
89 return vbgkqjMethod;
90 },
91 set(_) {},
92 },
93 xzfiflffffi: { configurable: true, enumerable: false, set(_) {} },
94 [symbol]: {
95 configurable: true,
96 enumerable: false,
97 value: "failure",
98 writable: true,
99 },
100 },
101 );
102
103 it("[[Call]] throws an error", () => {
104 assertThrows(() => LazyLoader({}));
105 });
106
107 it("[[Construct]] creates a new object which inherits from the correct prototype", () => {
108 assertStrictEquals(
109 Object.getPrototypeOf(new LazyLoader(methodsObject)),
110 prototype,
111 );
112 });
113
114 it("[[Construct]] creates a new object with the desired properties", () => {
115 assertEquals(
116 Reflect.ownKeys(new LazyLoader(methodsObject)),
117 ["etaoin", "shrdlu", "cmfwyp", "vbgkqj", "xzfiflffffi", symbol],
118 );
119 });
120
121 it("[[Construct]] creates a new object with configurable properties", () => {
122 assertEquals(
123 Object.fromEntries(
124 function* (ll) {
125 for (const key of Reflect.ownKeys(ll)) {
126 yield [
127 key,
128 Object.getOwnPropertyDescriptor(ll, key).configurable,
129 ];
130 }
131 }(new LazyLoader(methodsObject)),
132 ),
133 {
134 etaoin: true,
135 shrdlu: true,
136 cmfwyp: true,
137 vbgkqj: true,
138 xzfiflffffi: true,
139 [symbol]: true,
140 },
141 );
142 });
143
144 it("[[Construct]] creates a new object with the correct enumerability", () => {
145 assertEquals(
146 Object.fromEntries(
147 function* (ll) {
148 for (const key of Reflect.ownKeys(ll)) {
149 yield [
150 key,
151 Object.getOwnPropertyDescriptor(ll, key).enumerable,
152 ];
153 }
154 }(new LazyLoader(methodsObject)),
155 ),
156 {
157 etaoin: true,
158 shrdlu: false,
159 cmfwyp: false,
160 vbgkqj: true,
161 xzfiflffffi: false,
162 [symbol]: false,
163 },
164 );
165 });
166
167 it("[[Construct]] creates a new object with defined getters", () => {
168 assertEquals(
169 Object.fromEntries(
170 function* (ll) {
171 for (const key of Reflect.ownKeys(ll)) {
172 yield [
173 key,
174 Object.getOwnPropertyDescriptor(ll, key).get?.name,
175 ];
176 }
177 }(new LazyLoader(methodsObject)),
178 ),
179 {
180 etaoin: "get etaoin",
181 shrdlu: "get shrdlu",
182 cmfwyp: "get cmfwyp",
183 vbgkqj: "get vbgkqj",
184 xzfiflffffi: "get xzfiflffffi",
185 [symbol]: `get [${symbol.description}]`,
186 },
187 );
188 });
189
190 it("[[Construct]] creates a new object with defined setters for writable properties only", () => {
191 assertEquals(
192 Object.fromEntries(
193 function* (ll) {
194 for (const key of Reflect.ownKeys(ll)) {
195 yield [
196 key,
197 Object.getOwnPropertyDescriptor(ll, key).set?.name,
198 ];
199 }
200 }(new LazyLoader(methodsObject)),
201 ),
202 {
203 etaoin: undefined,
204 shrdlu: undefined,
205 cmfwyp: undefined,
206 vbgkqj: undefined,
207 xzfiflffffi: undefined,
208 [symbol]: `set [${symbol.description}]`,
209 },
210 );
211 });
212
213 it("[[Construct]] creates a new object with correct getter behaviour", () => {
214 const ll = new LazyLoader(methodsObject);
215 ll.etaoin;
216 assertEquals(
217 Object.getOwnPropertyDescriptor(ll, "etaoin"),
218 {
219 configurable: false,
220 enumerable: true,
221 value: "success",
222 writable: false,
223 },
224 );
225 assertSpyCalls(etaoinMethod, 1);
226 assertSpyCall(etaoinMethod, 0, {
227 args: [],
228 self: ll,
229 returned: "success",
230 });
231 ll.shrdlu;
232 assertEquals(
233 Object.getOwnPropertyDescriptor(ll, "shrdlu"),
234 {
235 configurable: true,
236 enumerable: false,
237 value: "success",
238 writable: false,
239 },
240 );
241 assertSpyCalls(shrdluMethod, 1);
242 assertSpyCall(shrdluMethod, 0, {
243 args: [],
244 self: ll,
245 returned: "success",
246 });
247 ll.cmfwyp;
248 assertEquals(
249 Object.getOwnPropertyDescriptor(ll, "cmfwyp"),
250 {
251 configurable: true,
252 enumerable: false,
253 value: "success",
254 writable: false,
255 },
256 );
257 assertSpyCalls(cmfwypMethod, 1);
258 assertSpyCall(cmfwypMethod, 0, {
259 args: [],
260 self: ll,
261 returned: "success",
262 });
263 ll.vbgkqj;
264 assertEquals(
265 Object.getOwnPropertyDescriptor(ll, "vbgkqj"),
266 {
267 configurable: false,
268 enumerable: true,
269 value: "success",
270 writable: false,
271 },
272 );
273 assertSpyCalls(vbgkqjMethod, 1);
274 assertSpyCall(vbgkqjMethod, 0, {
275 args: [],
276 self: ll,
277 returned: "success",
278 });
279 assertThrows(() => ll.xzfiflffffi);
280 assertThrows(() => ll[symbol]);
281 });
282
283 it("[[Construct]] creates a new object with correct setter behaviour", () => {
284 const ll = new LazyLoader(methodsObject);
285 ll[symbol] = "success";
286 assertEquals(
287 Object.getOwnPropertyDescriptor(ll, symbol),
288 {
289 configurable: true,
290 enumerable: false,
291 value: "success",
292 writable: true,
293 },
294 );
295 });
296
297 describe(".length", () => {
298 it("[[Get]] returns the correct length", () => {
299 assertStrictEquals(LazyLoader.length, 1);
300 });
301 });
302
303 describe(".name", () => {
304 it("[[Get]] returns the correct name", () => {
305 assertStrictEquals(LazyLoader.name, "LazyLoader");
306 });
307 });
308 });
309
310 describe("PropertyDescriptor", () => {
311 it("[[Call]] throws an error", () => {
312 assertThrows(() => PropertyDescriptor({}));
313 });
314
315 it("[[Construct]] creates a new PropertyDescriptor", () => {
316 assertStrictEquals(
317 Object.getPrototypeOf(new PropertyDescriptor({})),
318 PropertyDescriptor.prototype,
319 );
320 });
321
322 it("[[Construct]] throws for primitives", () => {
323 assertThrows(() => new PropertyDescriptor("failure"));
324 });
325
326 describe(".length", () => {
327 it("[[Get]] returns the correct length", () => {
328 assertStrictEquals(PropertyDescriptor.length, 1);
329 });
330 });
331
332 describe(".name", () => {
333 it("[[Get]] returns the correct name", () => {
334 assertStrictEquals(
335 PropertyDescriptor.name,
336 "PropertyDescriptor",
337 );
338 });
339 });
340
341 describe("::complete", () => {
342 it("[[Call]] completes a generic descriptor", () => {
343 const desc = {};
344 PropertyDescriptor.prototype.complete.call(desc);
345 assertEquals(desc, {
346 configurable: false,
347 enumerable: false,
348 value: undefined,
349 writable: false,
350 });
351 });
352
353 it("[[Call]] completes a data descriptor", () => {
354 const desc = { value: undefined };
355 PropertyDescriptor.prototype.complete.call(desc);
356 assertEquals(desc, {
357 configurable: false,
358 enumerable: false,
359 value: undefined,
360 writable: false,
361 });
362 });
363
364 it("[[Call]] completes an accessor descriptor", () => {
365 const desc = { get: undefined };
366 PropertyDescriptor.prototype.complete.call(desc);
367 assertEquals(desc, {
368 configurable: false,
369 enumerable: false,
370 get: undefined,
371 set: undefined,
372 });
373 });
374
375 describe(".length", () => {
376 it("[[Get]] returns the correct length", () => {
377 assertStrictEquals(
378 PropertyDescriptor.prototype.complete.length,
379 0,
380 );
381 });
382 });
383
384 describe(".name", () => {
385 it("[[Get]] returns the correct name", () => {
386 assertStrictEquals(
387 PropertyDescriptor.prototype.complete.name,
388 "complete",
389 );
390 });
391 });
392 });
393
394 describe("::isAccessorDescriptor", () => {
395 it("[[Get]] returns false for a generic descriptor", () => {
396 assertStrictEquals(
397 Reflect.get(
398 PropertyDescriptor.prototype,
399 "isAccessorDescriptor",
400 {},
401 ),
402 false,
403 );
404 });
405
406 it("[[Get]] returns false for a data descriptor", () => {
407 assertStrictEquals(
408 Reflect.get(
409 PropertyDescriptor.prototype,
410 "isAccessorDescriptor",
411 { value: undefined },
412 ),
413 false,
414 );
415 });
416
417 it("[[Get]] returns true for an accessor descriptor", () => {
418 assertStrictEquals(
419 Reflect.get(
420 PropertyDescriptor.prototype,
421 "isAccessorDescriptor",
422 { get: undefined },
423 ),
424 true,
425 );
426 });
427
428 describe("[[GetOwnProperty]].get.length", () => {
429 it("[[Get]] returns the correct length", () => {
430 assertStrictEquals(
431 Object.getOwnPropertyDescriptor(
432 PropertyDescriptor.prototype,
433 "isAccessorDescriptor",
434 ).get.length,
435 0,
436 );
437 });
438 });
439
440 describe("[[GetOwnProperty]].get.name", () => {
441 it("[[Get]] returns the correct name", () => {
442 assertStrictEquals(
443 Object.getOwnPropertyDescriptor(
444 PropertyDescriptor.prototype,
445 "isAccessorDescriptor",
446 ).get.name,
447 "get isAccessorDescriptor",
448 );
449 });
450 });
451 });
452
453 describe("::isDataDescriptor", () => {
454 it("[[Get]] returns false for a generic descriptor", () => {
455 assertStrictEquals(
456 Reflect.get(
457 PropertyDescriptor.prototype,
458 "isDataDescriptor",
459 {},
460 ),
461 false,
462 );
463 });
464
465 it("[[Get]] returns true for a data descriptor", () => {
466 assertStrictEquals(
467 Reflect.get(
468 PropertyDescriptor.prototype,
469 "isDataDescriptor",
470 { value: undefined },
471 ),
472 true,
473 );
474 });
475
476 it("[[Get]] returns false for an accessor descriptor", () => {
477 assertStrictEquals(
478 Reflect.get(
479 PropertyDescriptor.prototype,
480 "isDataDescriptor",
481 { get: undefined },
482 ),
483 false,
484 );
485 });
486
487 describe("[[GetOwnProperty]].get.length", () => {
488 it("[[Get]] returns the correct length", () => {
489 assertStrictEquals(
490 Object.getOwnPropertyDescriptor(
491 PropertyDescriptor.prototype,
492 "isDataDescriptor",
493 ).get.length,
494 0,
495 );
496 });
497 });
498
499 describe("[[GetOwnProperty]].get.name", () => {
500 it("[[Get]] returns the correct name", () => {
501 assertStrictEquals(
502 Object.getOwnPropertyDescriptor(
503 PropertyDescriptor.prototype,
504 "isDataDescriptor",
505 ).get.name,
506 "get isDataDescriptor",
507 );
508 });
509 });
510 });
511
512 describe("::isFullyPopulated", () => {
513 it("[[Get]] returns false for a generic descriptor", () => {
514 assertStrictEquals(
515 Reflect.get(
516 PropertyDescriptor.prototype,
517 "isFullyPopulated",
518 {},
519 ),
520 false,
521 );
522 });
523
524 it("[[Get]] returns false for a non‐fully‐populated data descriptor", () => {
525 assertStrictEquals(
526 Reflect.get(
527 PropertyDescriptor.prototype,
528 "isFullyPopulated",
529 { value: undefined },
530 ),
531 false,
532 );
533 });
534
535 it("[[Get]] returns true for a fully‐populated data descriptor", () => {
536 assertStrictEquals(
537 Reflect.get(PropertyDescriptor.prototype, "isFullyPopulated", {
538 configurable: true,
539 enumerable: true,
540 value: undefined,
541 writable: true,
542 }),
543 true,
544 );
545 });
546
547 it("[[Get]] returns false for a non‐fully‐populated accessor descriptor", () => {
548 assertStrictEquals(
549 Reflect.get(
550 PropertyDescriptor.prototype,
551 "isFullyPopulated",
552 { get: undefined },
553 ),
554 false,
555 );
556 });
557
558 it("[[Get]] returns true for a fully‐populated accessor descriptor", () => {
559 assertStrictEquals(
560 Reflect.get(PropertyDescriptor.prototype, "isFullyPopulated", {
561 configurable: true,
562 enumerable: true,
563 get: undefined,
564 set: undefined,
565 }),
566 true,
567 );
568 });
569
570 describe("[[GetOwnProperty]].get.length", () => {
571 it("[[Get]] returns the correct length", () => {
572 assertStrictEquals(
573 Object.getOwnPropertyDescriptor(
574 PropertyDescriptor.prototype,
575 "isFullyPopulated",
576 ).get.length,
577 0,
578 );
579 });
580 });
581
582 describe("[[GetOwnProperty]].get.name", () => {
583 it("[[Get]] returns the correct name", () => {
584 assertStrictEquals(
585 Object.getOwnPropertyDescriptor(
586 PropertyDescriptor.prototype,
587 "isFullyPopulated",
588 ).get.name,
589 "get isFullyPopulated",
590 );
591 });
592 });
593 });
594
595 describe("::isGenericDescriptor", () => {
596 it("[[Get]] returns true for a generic descriptor", () => {
597 assertStrictEquals(
598 Reflect.get(
599 PropertyDescriptor.prototype,
600 "isGenericDescriptor",
601 {},
602 ),
603 true,
604 );
605 });
606
607 it("[[Get]] returns true for a data descriptor", () => {
608 assertStrictEquals(
609 Reflect.get(
610 PropertyDescriptor.prototype,
611 "isGenericDescriptor",
612 { value: undefined },
613 ),
614 false,
615 );
616 });
617
618 it("[[Get]] returns false for an accessor descriptor", () => {
619 assertStrictEquals(
620 Reflect.get(
621 PropertyDescriptor.prototype,
622 "isGenericDescriptor",
623 { get: undefined },
624 ),
625 false,
626 );
627 });
628
629 describe("[[GetOwnProperty]].get.length", () => {
630 it("[[Get]] returns the correct length", () => {
631 assertStrictEquals(
632 Object.getOwnPropertyDescriptor(
633 PropertyDescriptor.prototype,
634 "isGenericDescriptor",
635 ).get.length,
636 0,
637 );
638 });
639 });
640
641 describe("[[GetOwnProperty]].get.name", () => {
642 it("[[Get]] returns the correct name", () => {
643 assertStrictEquals(
644 Object.getOwnPropertyDescriptor(
645 PropertyDescriptor.prototype,
646 "isGenericDescriptor",
647 ).get.name,
648 "get isGenericDescriptor",
649 );
650 });
651 });
652 });
653
654 describe("~configurable", () => {
655 it("[[DefineOwnProperty]] coerces to a boolean", () => {
656 const desc = new PropertyDescriptor({});
657 Object.defineProperty(desc, "configurable", {});
658 assertStrictEquals(desc.configurable, false);
659 });
660
661 it("[[DefineOwnProperty]] throws for accessor properties", () => {
662 const desc = new PropertyDescriptor({});
663 assertThrows(() =>
664 Object.defineProperty(desc, "configurable", { get: undefined })
665 );
666 });
667
668 it("[[Set]] coerces to a boolean", () => {
669 const desc = new PropertyDescriptor({});
670 desc.configurable = undefined;
671 assertStrictEquals(desc.configurable, false);
672 });
673
674 it("[[Delete]] works", () => {
675 const desc = new PropertyDescriptor({ configurable: false });
676 delete desc.configurable;
677 assert(!("configurable" in desc));
678 });
679 });
680
681 describe("~enumerable", () => {
682 it("[[DefineOwnProperty]] coerces to a boolean", () => {
683 const desc = new PropertyDescriptor({});
684 Object.defineProperty(desc, "enumerable", {});
685 assertStrictEquals(desc.enumerable, false);
686 });
687
688 it("[[DefineOwnProperty]] throws for accessor properties", () => {
689 const desc = new PropertyDescriptor({});
690 assertThrows(() =>
691 Object.defineProperty(desc, "enumerable", { get: undefined })
692 );
693 });
694
695 it("[[Set]] coerces to a boolean", () => {
696 const desc = new PropertyDescriptor({});
697 desc.enumerable = undefined;
698 assertStrictEquals(desc.enumerable, false);
699 });
700
701 it("[[Delete]] works", () => {
702 const desc = new PropertyDescriptor({ enumerable: false });
703 delete desc.enumerable;
704 assert(!("enumerable" in desc));
705 });
706 });
707
708 describe("~get", () => {
709 it("[[DefineOwnProperty]] works", () => {
710 const desc = new PropertyDescriptor({});
711 Object.defineProperty(desc, "get", {});
712 assertStrictEquals(desc.get, undefined);
713 });
714
715 it("[[DefineOwnProperty]] throws for accessor properties", () => {
716 const desc = new PropertyDescriptor({});
717 assertThrows(() =>
718 Object.defineProperty(desc, "get", { get: undefined })
719 );
720 });
721
722 it("[[DefineOwnProperty]] throws if not callable or undefined", () => {
723 const desc = new PropertyDescriptor({});
724 assertThrows(
725 () => Object.defineProperty(desc, "get", { value: null }),
726 );
727 });
728
729 it("[[DefineOwnProperty]] throws if a data property is defined", () => {
730 const desc = new PropertyDescriptor({ value: undefined });
731 assertThrows(() => Object.defineProperty(desc, "get", {}));
732 });
733
734 it("[[Set]] works", () => {
735 const desc = new PropertyDescriptor({});
736 const fn = () => {};
737 desc.get = fn;
738 assertStrictEquals(desc.get, fn);
739 });
740
741 it("[[Set]] throws if not callable or undefined", () => {
742 const desc = new PropertyDescriptor({});
743 assertThrows(() => desc.get = null);
744 });
745
746 it("[[Set]] throws if a data property is defined", () => {
747 const desc = new PropertyDescriptor({ value: undefined });
748 assertThrows(() => desc.get = undefined);
749 });
750
751 it("[[Delete]] works", () => {
752 const desc = new PropertyDescriptor({ get: undefined });
753 delete desc.get;
754 assert(!("get" in desc));
755 });
756 });
757
758 describe("~set", () => {
759 it("[[DefineOwnProperty]] works", () => {
760 const desc = new PropertyDescriptor({});
761 Object.defineProperty(desc, "set", {});
762 assertStrictEquals(desc.set, undefined);
763 });
764
765 it("[[DefineOwnProperty]] throws for accessor properties", () => {
766 const desc = new PropertyDescriptor({});
767 assertThrows(() =>
768 Object.defineProperty(desc, "set", { get: undefined })
769 );
770 });
771
772 it("[[DefineOwnProperty]] throws if not callable or undefined", () => {
773 const desc = new PropertyDescriptor({});
774 assertThrows(
775 () => Object.defineProperty(desc, "set", { value: null }),
776 );
777 });
778
779 it("[[DefineOwnProperty]] throws if a data property is defined", () => {
780 const desc = new PropertyDescriptor({ value: undefined });
781 assertThrows(() => Object.defineProperty(desc, "set", {}));
782 });
783
784 it("[[Set]] works", () => {
785 const desc = new PropertyDescriptor({});
786 const fn = (_) => {};
787 desc.set = fn;
788 assertStrictEquals(desc.set, fn);
789 });
790
791 it("[[Set]] throws if not callable or undefined", () => {
792 const desc = new PropertyDescriptor({});
793 assertThrows(() => desc.set = null);
794 });
795
796 it("[[Set]] throws if a data property is defined", () => {
797 const desc = new PropertyDescriptor({ value: undefined });
798 assertThrows(() => desc.set = undefined);
799 });
800
801 it("[[Delete]] works", () => {
802 const desc = new PropertyDescriptor({ set: undefined });
803 delete desc.set;
804 assert(!("set" in desc));
805 });
806 });
807
808 describe("~value", () => {
809 it("[[DefineOwnProperty]] works", () => {
810 const desc = new PropertyDescriptor({});
811 Object.defineProperty(desc, "value", {});
812 assertStrictEquals(desc.value, undefined);
813 });
814
815 it("[[DefineOwnProperty]] throws for accessor properties", () => {
816 const desc = new PropertyDescriptor({});
817 assertThrows(() =>
818 Object.defineProperty(desc, "value", { get: undefined })
819 );
820 });
821
822 it("[[DefineOwnProperty]] throws if an accessor property is defined", () => {
823 const desc = new PropertyDescriptor({ get: undefined });
824 assertThrows(() => Object.defineProperty(desc, "value", {}));
825 });
826
827 it("[[Set]] works", () => {
828 const desc = new PropertyDescriptor({});
829 desc.value = "success";
830 assertStrictEquals(desc.value, "success");
831 });
832
833 it("[[Set]] throws if an accessor property is defined", () => {
834 const desc = new PropertyDescriptor({ get: undefined });
835 assertThrows(() => desc.value = null);
836 });
837
838 it("[[Delete]] works", () => {
839 const desc = new PropertyDescriptor({ value: undefined });
840 delete desc.value;
841 assert(!("value" in desc));
842 });
843 });
844
845 describe("~writable", () => {
846 it("[[DefineOwnProperty]] coerces to a boolean", () => {
847 const desc = new PropertyDescriptor({});
848 Object.defineProperty(desc, "writable", {});
849 assertStrictEquals(desc.writable, false);
850 });
851
852 it("[[DefineOwnProperty]] throws for accessor properties", () => {
853 const desc = new PropertyDescriptor({});
854 assertThrows(() =>
855 Object.defineProperty(desc, "writable", { get: undefined })
856 );
857 });
858
859 it("[[DefineOwnProperty]] throws if an accessor property is defined", () => {
860 const desc = new PropertyDescriptor({ get: undefined });
861 assertThrows(() => Object.defineProperty(desc, "writable", {}));
862 });
863
864 it("[[Set]] coerces to a boolean", () => {
865 const desc = new PropertyDescriptor({});
866 desc.writable = undefined;
867 assertStrictEquals(desc.writable, false);
868 });
869
870 it("[[Set]] throws if an accessor property is defined", () => {
871 const desc = new PropertyDescriptor({ get: undefined });
872 assertThrows(() => desc.writable = false);
873 });
874
875 it("[[Delete]] works", () => {
876 const desc = new PropertyDescriptor({ writable: false });
877 delete desc.writable;
878 assert(!("writable" in desc));
879 });
880 });
881 });
882
883 describe("defineOwnProperty", () => {
884 it("[[Call]] defines the property", () => {
885 const obj = {};
886 defineOwnProperty(obj, "etaoin", {});
887 assert("etaoin" in obj);
888 });
889
890 it("[[Call]] returns the provided object", () => {
891 const obj = {};
892 assertStrictEquals(defineOwnProperty(obj, "etaoin", {}), obj);
893 });
894
895 it("[[Construct]] throws an error", () => {
896 assertThrows(() => new defineOwnProperty(obj, "etaoin", {}));
897 });
898
899 describe(".length", () => {
900 it("[[Get]] returns the correct length", () => {
901 assertStrictEquals(defineOwnProperty.length, 3);
902 });
903 });
904
905 describe(".name", () => {
906 it("[[Get]] returns the correct name", () => {
907 assertStrictEquals(
908 defineOwnProperty.name,
909 "defineOwnProperty",
910 );
911 });
912 });
913 });
914
915 describe("defineOwnProperties", () => {
916 it("[[Call]] defines properties from the provided objects", () => {
917 const obj = {};
918 defineOwnProperties(obj, {
919 etaoin: {},
920 shrdlu: {},
921 }, { cmfwyp: {} });
922 assert("etaoin" in obj);
923 assert("shrdlu" in obj);
924 assert("cmfwyp" in obj);
925 });
926
927 it("[[Call]] overrides earlier declarations with later ones", () => {
928 const obj = { etaoin: undefined };
929 defineOwnProperties(obj, {
930 etaoin: { value: "failure" },
931 }, {
932 etaoin: { value: "success" },
933 });
934 assertStrictEquals(obj.etaoin, "success");
935 });
936
937 it("[[Call]] returns the provided object", () => {
938 const obj = {};
939 assertStrictEquals(defineOwnProperties(obj), obj);
940 });
941
942 it("[[Construct]] throws an error", () => {
943 assertThrows(() => new defineOwnProperties({}));
944 });
945
946 describe(".length", () => {
947 it("[[Get]] returns the correct length", () => {
948 assertStrictEquals(defineOwnProperties.length, 1);
949 });
950 });
951
952 describe(".name", () => {
953 it("[[Get]] returns the correct name", () => {
954 assertStrictEquals(
955 defineOwnProperties.name,
956 "defineOwnProperties",
957 );
958 });
959 });
960 });
961
962 describe("deleteOwnProperty", () => {
963 it("[[Call]] deletes the provided property on the provided object", () => {
964 const obj = { failure: undefined };
965 deleteOwnProperty(obj, "failure");
966 assert(!("failure" in obj));
967 });
968
969 it("[[Call]] does nothing if the property doesn’t exist", () => {
970 const obj = Object.freeze({});
971 deleteOwnProperty(obj, "failure");
972 assert(!("failure" in obj));
973 });
974
975 it("[[Call]] throws if the property can’t be deleted", () => {
976 const obj = Object.seal({ failure: undefined });
977 assertThrows(() => deleteOwnProperty(obj, "failure"));
978 });
979
980 it("[[Call]] returns the provided object", () => {
981 const obj = {};
982 assertStrictEquals(deleteOwnProperty(obj, ""), obj);
983 });
984
985 it("[[Construct]] throws an error", () => {
986 assertThrows(() => new deleteOwnProperty({}, ""));
987 });
988
989 describe(".length", () => {
990 it("[[Get]] returns the correct length", () => {
991 assertStrictEquals(deleteOwnProperty.length, 2);
992 });
993 });
994
995 describe(".name", () => {
996 it("[[Get]] returns the correct name", () => {
997 assertStrictEquals(deleteOwnProperty.name, "deleteOwnProperty");
998 });
999 });
1000 });
1001
1002 describe("freeze", () => {
1003 it("[[Call]] freezes the object", () => {
1004 const obj = {};
1005 freeze(obj);
1006 assert(Object.isFrozen(obj));
1007 });
1008
1009 it("[[Call]] returns the provided object", () => {
1010 const obj = {};
1011 assertStrictEquals(freeze(obj), obj);
1012 });
1013
1014 it("[[Construct]] throws an error", () => {
1015 assertThrows(() => new freeze({}));
1016 });
1017
1018 describe(".length", () => {
1019 it("[[Get]] returns the correct length", () => {
1020 assertStrictEquals(freeze.length, 1);
1021 });
1022 });
1023
1024 describe(".name", () => {
1025 it("[[Get]] returns the correct name", () => {
1026 assertStrictEquals(freeze.name, "freeze");
1027 });
1028 });
1029 });
1030
1031 describe("frozenCopy", () => {
1032 it("[[Call]] returns a frozen object", () => {
1033 assert(
1034 Object.isFrozen(
1035 frozenCopy(Object.create(null), {
1036 data: {
1037 configurable: true,
1038 enumerable: true,
1039 value: undefined,
1040 writable: true,
1041 },
1042 accessor: {
1043 configurable: true,
1044 enumerable: true,
1045 get: undefined,
1046 },
1047 }),
1048 ),
1049 );
1050 });
1051
1052 it("[[Call]] ignores non·enumerable properties", () => {
1053 assertEquals(
1054 frozenCopy(
1055 Object.create(null, {
1056 data: { value: undefined },
1057 accessor: { get: undefined },
1058 }),
1059 ),
1060 {},
1061 );
1062 });
1063
1064 it("[[Call]] preserves accessor properties", () => {
1065 const properties = {
1066 both: {
1067 configurable: false,
1068 enumerable: true,
1069 get: () => {},
1070 set: (_) => {},
1071 },
1072 empty: {
1073 configurable: false,
1074 enumerable: true,
1075 get: undefined,
1076 set: undefined,
1077 },
1078 getter: {
1079 configurable: false,
1080 enumerable: true,
1081 get: () => {},
1082 set: undefined,
1083 },
1084 setter: {
1085 configurable: false,
1086 enumerable: true,
1087 get: undefined,
1088 set: (_) => {},
1089 },
1090 };
1091 assertEquals(
1092 Object.getOwnPropertyDescriptors(
1093 frozenCopy(Object.create(null, properties)),
1094 ),
1095 properties,
1096 );
1097 });
1098
1099 it("[[Call]] does not copy properties on the prototype", () => {
1100 assert(
1101 !("failure" in
1102 frozenCopy(Object.create({ failure: undefined }), {
1103 data: {
1104 configurable: true,
1105 value: undefined,
1106 writable: true,
1107 },
1108 accessor: { configurable: true, get: undefined },
1109 })),
1110 );
1111 });
1112
1113 it("[[Call]] uses the species of the constructor", () => {
1114 const species = { prototype: {} };
1115 assertStrictEquals(
1116 Object.getPrototypeOf(
1117 frozenCopy({}, { [Symbol.species]: species }),
1118 ),
1119 species.prototype,
1120 );
1121 });
1122
1123 it("[[Call]] uses constructor if no species is defined", () => {
1124 const constructor = { [Symbol.species]: null, prototype: {} };
1125 assertStrictEquals(
1126 Object.getPrototypeOf(frozenCopy({}, constructor)),
1127 constructor.prototype,
1128 );
1129 });
1130
1131 it("[[Call]] uses the constructor on the object if none is provided", () => {
1132 const constructor = { [Symbol.species]: null, prototype: {} };
1133 assertStrictEquals(
1134 Object.getPrototypeOf(frozenCopy({ constructor })),
1135 constructor.prototype,
1136 );
1137 });
1138
1139 it("[[Call]] allows a null constructor", () => {
1140 assertStrictEquals(
1141 Object.getPrototypeOf(frozenCopy({}, null)),
1142 null,
1143 );
1144 });
1145
1146 it("[[Construct]] throws an error", () => {
1147 assertThrows(() => new frozenCopy({}));
1148 });
1149
1150 describe(".length", () => {
1151 it("[[Get]] returns the correct length", () => {
1152 assertStrictEquals(frozenCopy.length, 1);
1153 });
1154 });
1155
1156 describe(".name", () => {
1157 it("[[Get]] returns the correct name", () => {
1158 assertStrictEquals(frozenCopy.name, "frozenCopy");
1159 });
1160 });
1161 });
1162
1163 describe("getMethod", () => {
1164 it("[[Call]] gets a method", () => {
1165 const method = () => {};
1166 assertStrictEquals(getMethod({ method }, "method"), method);
1167 });
1168
1169 it("[[Call]] works for values coercible to objects", () => {
1170 assertEquals(getMethod("", "toString"), String.prototype.toString);
1171 });
1172
1173 it("[[Call]] throws for null and undefined", () => {
1174 assertThrows(() => getMethod(null, "valueOf"));
1175 assertThrows(() => getMethod(undefined, "valueOf"));
1176 });
1177
1178 it("[[Call]] throws if the resulting value isn’t callable", () => {
1179 assertThrows(() => getMethod({ "failure": true }, "failure"));
1180 });
1181
1182 it("[[Construct]] throws an error", () => {
1183 assertThrows(() => new getMethod({ method() {} }, "method"));
1184 });
1185
1186 describe(".length", () => {
1187 it("[[Get]] returns the correct length", () => {
1188 assertStrictEquals(getMethod.length, 2);
1189 });
1190 });
1191
1192 describe(".name", () => {
1193 it("[[Get]] returns the correct name", () => {
1194 assertStrictEquals(getMethod.name, "getMethod");
1195 });
1196 });
1197 });
1198
1199 describe("getOwnPropertyDescriptor", () => {
1200 it("[[Call]] gets the descriptor", () => {
1201 assertEquals(
1202 getOwnPropertyDescriptor({ success: true }, "success"),
1203 {
1204 configurable: true,
1205 enumerable: true,
1206 value: true,
1207 writable: true,
1208 },
1209 );
1210 });
1211
1212 it("[[Call]] returns undefined for non‐own properties", () => {
1213 assertStrictEquals(
1214 getOwnPropertyDescriptor({}, "valueOf"),
1215 undefined,
1216 );
1217 });
1218
1219 it("[[Construct]] throws an error", () => {
1220 assertThrows(() => new getOwnPropertyDescriptor({}, ""));
1221 });
1222
1223 describe(".length", () => {
1224 it("[[Get]] returns the correct length", () => {
1225 assertStrictEquals(getOwnPropertyDescriptor.length, 2);
1226 });
1227 });
1228
1229 describe(".name", () => {
1230 it("[[Get]] returns the correct name", () => {
1231 assertStrictEquals(
1232 getOwnPropertyDescriptor.name,
1233 "getOwnPropertyDescriptor",
1234 );
1235 });
1236 });
1237 });
1238
1239 describe("getOwnPropertyDescriptors", () => {
1240 it("[[Call]] gets the descriptors", () => {
1241 assertEquals(
1242 getOwnPropertyDescriptors({ success: true, etaoin: "shrdlu" }),
1243 {
1244 success: {
1245 configurable: true,
1246 enumerable: true,
1247 value: true,
1248 writable: true,
1249 },
1250 etaoin: {
1251 configurable: true,
1252 enumerable: true,
1253 value: "shrdlu",
1254 writable: true,
1255 },
1256 },
1257 );
1258 });
1259
1260 it("[[Construct]] throws an error", () => {
1261 assertThrows(() => new getOwnPropertyDescriptors({}));
1262 });
1263
1264 describe(".length", () => {
1265 it("[[Get]] returns the correct length", () => {
1266 assertStrictEquals(getOwnPropertyDescriptors.length, 1);
1267 });
1268 });
1269
1270 describe(".name", () => {
1271 it("[[Get]] returns the correct name", () => {
1272 assertStrictEquals(
1273 getOwnPropertyDescriptors.name,
1274 "getOwnPropertyDescriptors",
1275 );
1276 });
1277 });
1278 });
1279
1280 describe("getOwnPropertyKeys", () => {
1281 it("[[Call]] gets own (but not inherited) property keys", () => {
1282 assertEquals(getOwnPropertyKeys({ success: true }), ["success"]);
1283 });
1284
1285 it("[[Call]] works for values coercible to objects", () => {
1286 assertEquals(getOwnPropertyKeys("foo"), ["0", "1", "2", "length"]);
1287 });
1288
1289 it("[[Call]] throws for null and undefined", () => {
1290 assertThrows(() => getOwnPropertyKeys(null));
1291 assertThrows(() => getOwnPropertyKeys(undefined));
1292 });
1293
1294 it("[[Construct]] throws an error", () => {
1295 assertThrows(() => new getOwnPropertyKeys({}));
1296 });
1297
1298 describe(".length", () => {
1299 it("[[Get]] returns the correct length", () => {
1300 assertStrictEquals(getOwnPropertyKeys.length, 1);
1301 });
1302 });
1303
1304 describe(".name", () => {
1305 it("[[Get]] returns the correct name", () => {
1306 assertStrictEquals(
1307 getOwnPropertyKeys.name,
1308 "getOwnPropertyKeys",
1309 );
1310 });
1311 });
1312 });
1313
1314 describe("getOwnPropertyStrings", () => {
1315 it("[[Call]] gets own string keys", () => {
1316 assertEquals(getOwnPropertyStrings({ success: true }), [
1317 "success",
1318 ]);
1319 });
1320
1321 it("[[Call]] works for values coercible to objects", () => {
1322 assertEquals(getOwnPropertyStrings("foo"), [
1323 "0",
1324 "1",
1325 "2",
1326 "length",
1327 ]);
1328 });
1329
1330 it("[[Call]] throws for null and undefined", () => {
1331 assertThrows(() => getOwnPropertyStrings(null));
1332 assertThrows(() => getOwnPropertyStrings(undefined));
1333 });
1334
1335 it("[[Construct]] throws an error", () => {
1336 assertThrows(() => new getOwnPropertyStrings({}));
1337 });
1338
1339 describe(".length", () => {
1340 it("[[Get]] returns the correct length", () => {
1341 assertStrictEquals(getOwnPropertyStrings.length, 1);
1342 });
1343 });
1344
1345 describe(".name", () => {
1346 it("[[Get]] returns the correct name", () => {
1347 assertStrictEquals(
1348 getOwnPropertyStrings.name,
1349 "getOwnPropertyStrings",
1350 );
1351 });
1352 });
1353 });
1354
1355 describe("getOwnPropertySymbols", () => {
1356 it("[[Call]] gets own symbol keys", () => {
1357 const sym = Symbol();
1358 assertEquals(getOwnPropertySymbols({ [sym]: true }), [sym]);
1359 });
1360
1361 it("[[Call]] works for values coercible to objects", () => {
1362 assertEquals(getOwnPropertySymbols("foo"), []);
1363 });
1364
1365 it("[[Call]] throws for null and undefined", () => {
1366 assertThrows(() => getOwnPropertySymbols(null));
1367 assertThrows(() => getOwnPropertySymbols(undefined));
1368 });
1369
1370 it("[[Construct]] throws an error", () => {
1371 assertThrows(() => new getOwnPropertySymbols({}));
1372 });
1373
1374 describe(".length", () => {
1375 it("[[Get]] returns the correct length", () => {
1376 assertStrictEquals(getOwnPropertySymbols.length, 1);
1377 });
1378 });
1379
1380 describe(".name", () => {
1381 it("[[Get]] returns the correct name", () => {
1382 assertStrictEquals(
1383 getOwnPropertySymbols.name,
1384 "getOwnPropertySymbols",
1385 );
1386 });
1387 });
1388 });
1389
1390 describe("getPropertyValue", () => {
1391 it("[[Call]] gets property values on the provided object", () => {
1392 assertStrictEquals(
1393 getPropertyValue({ success: true }, "success"),
1394 true,
1395 );
1396 });
1397
1398 it("[[Call]] works for values coercible to objects", () => {
1399 assertStrictEquals(
1400 getPropertyValue("", "toString"),
1401 String.prototype.toString,
1402 );
1403 });
1404
1405 it("[[Call]] throws for null and undefined", () => {
1406 assertThrows(() => getPropertyValue(null, "valueOf"));
1407 assertThrows(() => getPropertyValue(undefined, "valueOf"));
1408 });
1409
1410 it("[[Construct]] throws an error", () => {
1411 assertThrows(() => new getPropertyValue({}, "valueOf"));
1412 });
1413
1414 describe(".length", () => {
1415 it("[[Get]] returns the correct length", () => {
1416 assertStrictEquals(getPropertyValue.length, 2);
1417 });
1418 });
1419
1420 describe(".name", () => {
1421 it("[[Get]] returns the correct name", () => {
1422 assertStrictEquals(getPropertyValue.name, "getPropertyValue");
1423 });
1424 });
1425 });
1426
1427 describe("getPrototype", () => {
1428 it("[[Call]] gets object prototypes", () => {
1429 assertStrictEquals(getPrototype({}), Object.prototype);
1430 const proto = {};
1431 assertStrictEquals(getPrototype(Object.create(proto)), proto);
1432 });
1433
1434 it("[[Call]] gets null prototypes", () => {
1435 assertStrictEquals(getPrototype(Object.create(null)), null);
1436 });
1437
1438 it("[[Call]] gets prototypes for coercible primitives", () => {
1439 assertStrictEquals(getPrototype(1), Number.prototype);
1440 assertStrictEquals(getPrototype(Symbol()), Symbol.prototype);
1441 });
1442
1443 it("[[Call]] throws for null and undefined", () => {
1444 assertThrows(() => getPrototype(null));
1445 assertThrows(() => getPrototype(undefined));
1446 });
1447
1448 it("[[Construct]] throws an error", () => {
1449 assertThrows(() => new getPrototype({}));
1450 });
1451
1452 describe(".length", () => {
1453 it("[[Get]] returns the correct length", () => {
1454 assertStrictEquals(getPrototype.length, 1);
1455 });
1456 });
1457
1458 describe(".name", () => {
1459 it("[[Get]] returns the correct name", () => {
1460 assertStrictEquals(getPrototype.name, "getPrototype");
1461 });
1462 });
1463 });
1464
1465 describe("hasProperty", () => {
1466 it("[[Call]] gets whether a property exists on the provided object", () => {
1467 assertStrictEquals(
1468 hasProperty({ success: "etaoin" }, "success"),
1469 true,
1470 );
1471 assertStrictEquals(hasProperty({}, "hasOwnProperty"), true);
1472 });
1473
1474 it("[[Call]] works for values coercible to objects", () => {
1475 assertStrictEquals(hasProperty("", "length"), true);
1476 assertStrictEquals(hasProperty("", "toString"), true);
1477 });
1478
1479 it("[[Call]] throws for null and undefined", () => {
1480 assertThrows(() => hasProperty(null, "valueOf"));
1481 assertThrows(() => hasProperty(undefined, "valueOf"));
1482 });
1483
1484 it("[[Construct]] throws an error", () => {
1485 assertThrows(() => new hasProperty({}, "valueOf"));
1486 });
1487
1488 describe(".length", () => {
1489 it("[[Get]] returns the correct length", () => {
1490 assertStrictEquals(hasProperty.length, 2);
1491 });
1492 });
1493
1494 describe(".name", () => {
1495 it("[[Get]] returns the correct name", () => {
1496 assertStrictEquals(hasProperty.name, "hasProperty");
1497 });
1498 });
1499 });
1500
1501 describe("hasOwnProperty", () => {
1502 it("[[Call]] gets whether an own property exists on the provided object", () => {
1503 assertStrictEquals(
1504 hasOwnProperty({ success: "etaoin" }, "success"),
1505 true,
1506 );
1507 assertStrictEquals(hasOwnProperty({}, "hasOwnProperty"), false);
1508 });
1509
1510 it("[[Call]] works for values coercible to objects", () => {
1511 assertStrictEquals(hasOwnProperty("", "length"), true);
1512 assertStrictEquals(hasOwnProperty("", "toString"), false);
1513 });
1514
1515 it("[[Call]] throws for null and undefined", () => {
1516 assertThrows(() => hasOwnProperty(null, "valueOf"));
1517 assertThrows(() => hasOwnProperty(undefined, "valueOf"));
1518 });
1519
1520 it("[[Construct]] throws an error", () => {
1521 assertThrows(() => new hasOwnProperty({}, "valueOf"));
1522 });
1523
1524 describe(".length", () => {
1525 it("[[Get]] returns the correct length", () => {
1526 assertStrictEquals(hasOwnProperty.length, 2);
1527 });
1528 });
1529
1530 describe(".name", () => {
1531 it("[[Get]] returns the correct name", () => {
1532 assertStrictEquals(hasOwnProperty.name, "hasOwnProperty");
1533 });
1534 });
1535 });
1536
1537 describe("isExtensibleObject", () => {
1538 it("[[Call]] returns true for extensible objects", () => {
1539 assertStrictEquals(isExtensibleObject({}), true);
1540 });
1541
1542 it("[[Call]] returns false for coercible primitives", () => {
1543 assertStrictEquals(isExtensibleObject(1), false);
1544 assertStrictEquals(isExtensibleObject(Symbol()), false);
1545 });
1546
1547 it("[[Call]] returns false for non·extensible objects", () => {
1548 assertStrictEquals(
1549 isExtensibleObject(Object.preventExtensions({})),
1550 false,
1551 );
1552 });
1553
1554 it("[[Call]] returns false for null and undefined", () => {
1555 assertStrictEquals(isExtensibleObject(null), false);
1556 assertStrictEquals(isExtensibleObject(undefined), false);
1557 });
1558
1559 it("[[Construct]] throws an error", () => {
1560 assertThrows(() => new isExtensibleObject({}));
1561 });
1562
1563 describe(".length", () => {
1564 it("[[Get]] returns the correct length", () => {
1565 assertStrictEquals(isExtensibleObject.length, 1);
1566 });
1567 });
1568
1569 describe(".name", () => {
1570 it("[[Get]] returns the correct name", () => {
1571 assertStrictEquals(
1572 isExtensibleObject.name,
1573 "isExtensibleObject",
1574 );
1575 });
1576 });
1577 });
1578
1579 describe("isUnfrozenObject", () => {
1580 it("[[Call]] returns true for unfrozen objects", () => {
1581 assertStrictEquals(isUnfrozenObject({}), true);
1582 });
1583
1584 it("[[Call]] returns false for coercible primitives", () => {
1585 assertStrictEquals(isUnfrozenObject(1), false);
1586 assertStrictEquals(isUnfrozenObject(Symbol()), false);
1587 });
1588
1589 it("[[Call]] returns false for frozen objects", () => {
1590 assertStrictEquals(isUnfrozenObject(Object.freeze({})), false);
1591 });
1592
1593 it("[[Call]] returns false for null and undefined", () => {
1594 assertStrictEquals(isUnfrozenObject(null), false);
1595 assertStrictEquals(isUnfrozenObject(undefined), false);
1596 });
1597
1598 it("[[Construct]] throws an error", () => {
1599 assertThrows(() => new isUnfrozenObject({}));
1600 });
1601
1602 describe(".length", () => {
1603 it("[[Get]] returns the correct length", () => {
1604 assertStrictEquals(isUnfrozenObject.length, 1);
1605 });
1606 });
1607
1608 describe(".name", () => {
1609 it("[[Get]] returns the correct name", () => {
1610 assertStrictEquals(isUnfrozenObject.name, "isUnfrozenObject");
1611 });
1612 });
1613 });
1614
1615 describe("isUnsealedObject", () => {
1616 it("[[Call]] returns true for unsealed objects", () => {
1617 assertStrictEquals(isUnsealedObject({}), true);
1618 });
1619
1620 it("[[Call]] returns false for coercible primitives", () => {
1621 assertStrictEquals(isUnsealedObject(1), false);
1622 assertStrictEquals(isUnsealedObject(Symbol()), false);
1623 });
1624
1625 it("[[Call]] returns false for sealed objects", () => {
1626 assertStrictEquals(isUnsealedObject(Object.seal({})), false);
1627 });
1628
1629 it("[[Call]] returns false for null and undefined", () => {
1630 assertStrictEquals(isUnsealedObject(null), false);
1631 assertStrictEquals(isUnsealedObject(undefined), false);
1632 });
1633
1634 it("[[Construct]] throws an error", () => {
1635 assertThrows(() => new isUnsealedObject({}));
1636 });
1637
1638 describe(".length", () => {
1639 it("[[Get]] returns the correct length", () => {
1640 assertStrictEquals(isUnsealedObject.length, 1);
1641 });
1642 });
1643
1644 describe(".name", () => {
1645 it("[[Get]] returns the correct name", () => {
1646 assertStrictEquals(isUnsealedObject.name, "isUnsealedObject");
1647 });
1648 });
1649 });
1650
1651 describe("namedEntries", () => {
1652 it("[[Call]] gets named entries", () => {
1653 assertEquals(namedEntries({ success: true }), [["success", true]]);
1654 });
1655
1656 it("[[Call]] works for values coercible to objects", () => {
1657 assertEquals(namedEntries("foo"), [
1658 ["0", "f"],
1659 ["1", "o"],
1660 ["2", "o"],
1661 ]);
1662 });
1663
1664 it("[[Call]] throws for null and undefined", () => {
1665 assertThrows(() => namedEntries(null));
1666 assertThrows(() => namedEntries(undefined));
1667 });
1668
1669 it("[[Construct]] throws an error", () => {
1670 assertThrows(() => new namedEntries({}));
1671 });
1672
1673 describe(".length", () => {
1674 it("[[Get]] returns the correct length", () => {
1675 assertStrictEquals(namedEntries.length, 1);
1676 });
1677 });
1678
1679 describe(".name", () => {
1680 it("[[Get]] returns the correct name", () => {
1681 assertStrictEquals(namedEntries.name, "namedEntries");
1682 });
1683 });
1684 });
1685
1686 describe("namedKeys", () => {
1687 it("[[Call]] gets named keys", () => {
1688 assertEquals(namedKeys({ success: true }), ["success"]);
1689 });
1690
1691 it("[[Call]] works for values coercible to objects", () => {
1692 assertEquals(namedKeys("foo"), [
1693 "0",
1694 "1",
1695 "2",
1696 ]);
1697 });
1698
1699 it("[[Call]] throws for null and undefined", () => {
1700 assertThrows(() => namedKeys(null));
1701 assertThrows(() => namedKeys(undefined));
1702 });
1703
1704 it("[[Construct]] throws an error", () => {
1705 assertThrows(() => new namedKeys({}));
1706 });
1707
1708 describe(".length", () => {
1709 it("[[Get]] returns the correct length", () => {
1710 assertStrictEquals(namedKeys.length, 1);
1711 });
1712 });
1713
1714 describe(".name", () => {
1715 it("[[Get]] returns the correct name", () => {
1716 assertStrictEquals(namedKeys.name, "namedKeys");
1717 });
1718 });
1719 });
1720
1721 describe("namedValues", () => {
1722 it("[[Call]] gets named values", () => {
1723 assertEquals(namedValues({ success: true }), [true]);
1724 });
1725
1726 it("[[Call]] works for values coercible to objects", () => {
1727 assertEquals(namedValues("foo"), [
1728 "f",
1729 "o",
1730 "o",
1731 ]);
1732 });
1733
1734 it("[[Call]] throws for null and undefined", () => {
1735 assertThrows(() => namedValues(null));
1736 assertThrows(() => namedValues(undefined));
1737 });
1738
1739 it("[[Construct]] throws an error", () => {
1740 assertThrows(() => new namedValues({}));
1741 });
1742
1743 describe(".length", () => {
1744 it("[[Get]] returns the correct length", () => {
1745 assertStrictEquals(namedValues.length, 1);
1746 });
1747 });
1748
1749 describe(".name", () => {
1750 it("[[Get]] returns the correct name", () => {
1751 assertStrictEquals(namedValues.name, "namedValues");
1752 });
1753 });
1754 });
1755
1756 describe("objectCreate", () => {
1757 it("[[Call]] creates an object", () => {
1758 const obj = objectCreate(null);
1759 assertStrictEquals(Object(obj), obj);
1760 });
1761
1762 it("[[Call]] correctly sets the prototype", () => {
1763 const proto = {};
1764 assertStrictEquals(
1765 Object.getPrototypeOf(objectCreate(proto)),
1766 proto,
1767 );
1768 assertStrictEquals(
1769 Object.getPrototypeOf(objectCreate(null)),
1770 null,
1771 );
1772 });
1773
1774 it("[[Call]] correctly sets own properties", () => {
1775 assertEquals(
1776 Object.getOwnPropertyDescriptors(
1777 objectCreate(null, { success: { value: true } }),
1778 ),
1779 {
1780 success: {
1781 configurable: false,
1782 enumerable: false,
1783 value: true,
1784 writable: false,
1785 },
1786 },
1787 );
1788 });
1789
1790 it("[[Call]] throws for coercible primitives", () => {
1791 assertThrows(() => objectCreate(1));
1792 assertThrows(() => objectCreate(Symbol()));
1793 });
1794
1795 it("[[Call]] throws for undefined", () => {
1796 assertThrows(() => objectCreate(undefined));
1797 });
1798
1799 it("[[Construct]] throws an error", () => {
1800 assertThrows(() => new objectCreate({}));
1801 });
1802
1803 describe(".length", () => {
1804 it("[[Get]] returns the correct length", () => {
1805 assertStrictEquals(objectCreate.length, 2);
1806 });
1807 });
1808
1809 describe(".name", () => {
1810 it("[[Get]] returns the correct name", () => {
1811 assertStrictEquals(objectCreate.name, "objectCreate");
1812 });
1813 });
1814 });
1815
1816 describe("objectFromEntries", () => {
1817 it("[[Call]] creates an object", () => {
1818 const obj = objectFromEntries([]);
1819 assertStrictEquals(Object(obj), obj);
1820 });
1821
1822 it("[[Call]] correctly sets the prototype", () => {
1823 assertStrictEquals(
1824 Object.getPrototypeOf(objectFromEntries([])),
1825 Object.prototype,
1826 );
1827 });
1828
1829 it("[[Call]] correctly sets own properties", () => {
1830 assertEquals(
1831 Object.entries(objectFromEntries([["success", true]])),
1832 [["success", true]],
1833 );
1834 });
1835
1836 it("[[Call]] throws if the argument is not a nested arraylike", () => {
1837 assertThrows(() => objectFromEntries(1));
1838 assertThrows(() => objectFromEntries(Symbol()));
1839 assertThrows(() => objectFromEntries(null));
1840 assertThrows(() => objectFromEntries(undefined));
1841 assertThrows(() => objectFromEntries({}));
1842 assertThrows(() => objectFromEntries([undefined]));
1843 });
1844
1845 it("[[Construct]] throws an error", () => {
1846 assertThrows(() => new objectFromEntries([]));
1847 });
1848
1849 describe(".length", () => {
1850 it("[[Get]] returns the correct length", () => {
1851 assertStrictEquals(objectFromEntries.length, 1);
1852 });
1853 });
1854
1855 describe(".name", () => {
1856 it("[[Get]] returns the correct name", () => {
1857 assertStrictEquals(objectFromEntries.name, "objectFromEntries");
1858 });
1859 });
1860 });
1861
1862 describe("preventExtensions", () => {
1863 it("[[Call]] prevents extensions on the object", () => {
1864 const obj = {};
1865 preventExtensions(obj);
1866 assert(!Object.isExtensible(obj));
1867 });
1868
1869 it("[[Call]] returns the provided object", () => {
1870 const obj = {};
1871 assertStrictEquals(preventExtensions(obj), obj);
1872 });
1873
1874 it("[[Construct]] throws an error", () => {
1875 assertThrows(() => new preventExtensions({}));
1876 });
1877
1878 describe(".length", () => {
1879 it("[[Get]] returns the correct length", () => {
1880 assertStrictEquals(preventExtensions.length, 1);
1881 });
1882 });
1883
1884 describe(".name", () => {
1885 it("[[Get]] returns the correct name", () => {
1886 assertStrictEquals(preventExtensions.name, "preventExtensions");
1887 });
1888 });
1889 });
1890
1891 describe("seal", () => {
1892 it("[[Call]] seals the object", () => {
1893 const obj = {};
1894 seal(obj);
1895 assert(Object.isSealed(obj));
1896 });
1897
1898 it("[[Call]] returns the provided object", () => {
1899 const obj = {};
1900 assertStrictEquals(seal(obj), obj);
1901 });
1902
1903 it("[[Construct]] throws an error", () => {
1904 assertThrows(() => new seal({}));
1905 });
1906
1907 describe(".length", () => {
1908 it("[[Get]] returns the correct length", () => {
1909 assertStrictEquals(seal.length, 1);
1910 });
1911 });
1912
1913 describe(".name", () => {
1914 it("[[Get]] returns the correct name", () => {
1915 assertStrictEquals(seal.name, "seal");
1916 });
1917 });
1918 });
1919
1920 describe("setPropertyValue", () => {
1921 it("[[Call]] sets the provided property on the provided object", () => {
1922 const obj = {};
1923 setPropertyValue(obj, "success", true);
1924 assertStrictEquals(obj.success, true);
1925 });
1926
1927 it("[[Call]] calls setters", () => {
1928 const setter = spy((_) => {});
1929 const obj = Object.create(null, { success: { set: setter } });
1930 setPropertyValue(obj, "success", true);
1931 assertSpyCalls(setter, 1);
1932 assertSpyCall(setter, 0, {
1933 args: [true],
1934 self: obj,
1935 });
1936 });
1937
1938 it("[[Call]] walks the prototype chain", () => {
1939 const setter = spy((_) => {});
1940 const obj = Object.create(
1941 Object.create(null, { success: { set: setter } }),
1942 );
1943 setPropertyValue(obj, "success", true);
1944 assertSpyCalls(setter, 1);
1945 assertSpyCall(setter, 0, {
1946 args: [true],
1947 self: obj,
1948 });
1949 });
1950
1951 it("[[Call]] uses the provided receiver", () => {
1952 const setter = spy((_) => {});
1953 const obj = Object.create(null, { success: { set: setter } });
1954 const receiver = {};
1955 setPropertyValue(obj, "success", true, receiver);
1956 assertSpyCalls(setter, 1);
1957 assertSpyCall(setter, 0, {
1958 args: [true],
1959 self: receiver,
1960 });
1961 });
1962
1963 it("[[Call]] throws if the property can’t be set", () => {
1964 const obj = Object.freeze({ failure: undefined });
1965 assertThrows(() => setPropertyValue(obj, "failure", true));
1966 });
1967
1968 it("[[Call]] returns the provided object", () => {
1969 const obj = {};
1970 assertStrictEquals(setPropertyValue(obj, "", undefined), obj);
1971 });
1972
1973 it("[[Construct]] throws an error", () => {
1974 assertThrows(() => new setPropertyValue({}, "", undefined));
1975 });
1976
1977 describe(".length", () => {
1978 it("[[Get]] returns the correct length", () => {
1979 assertStrictEquals(setPropertyValue.length, 3);
1980 });
1981 });
1982
1983 describe(".name", () => {
1984 it("[[Get]] returns the correct name", () => {
1985 assertStrictEquals(setPropertyValue.name, "setPropertyValue");
1986 });
1987 });
1988 });
1989
1990 describe("setPropertyValues", () => {
1991 it("[[Call]] sets the provided properties on the provided object", () => {
1992 const obj = {};
1993 setPropertyValues(obj, { success: true, all: "good" });
1994 assertStrictEquals(obj.success, true);
1995 assertStrictEquals(obj.all, "good");
1996 });
1997
1998 it("[[Call]] can take multiple objects", () => {
1999 const obj = {};
2000 setPropertyValues(
2001 obj,
2002 { success: false, all: "good" },
2003 { success: true },
2004 );
2005 assertStrictEquals(obj.success, true);
2006 assertStrictEquals(obj.all, "good");
2007 });
2008
2009 it("[[Call]] ignores nullish arguments", () => {
2010 const obj = {};
2011 setPropertyValues(obj, null, undefined, { success: true });
2012 assertStrictEquals(obj.success, true);
2013 });
2014
2015 it("[[Call]] calls setters", () => {
2016 const setter = spy((_) => {});
2017 const obj = Object.create(null, { success: { set: setter } });
2018 setPropertyValues(obj, { success: true });
2019 assertSpyCalls(setter, 1);
2020 assertSpyCall(setter, 0, {
2021 args: [true],
2022 self: obj,
2023 });
2024 });
2025
2026 it("[[Call]] calls setters multiple times if property appears more than once", () => {
2027 const setter = spy((_) => {});
2028 const obj = Object.create(null, { success: { set: setter } });
2029 setPropertyValues(obj, { success: false }, { success: true });
2030 assertSpyCalls(setter, 2);
2031 assertSpyCall(setter, 0, {
2032 args: [false],
2033 self: obj,
2034 });
2035 assertSpyCall(setter, 1, {
2036 args: [true],
2037 self: obj,
2038 });
2039 });
2040
2041 it("[[Call]] walks the prototype chain", () => {
2042 const setter = spy((_) => {});
2043 const obj = Object.create(
2044 Object.create(null, { success: { set: setter } }),
2045 );
2046 setPropertyValues(obj, { success: true });
2047 assertSpyCalls(setter, 1);
2048 assertSpyCall(setter, 0, {
2049 args: [true],
2050 self: obj,
2051 });
2052 });
2053
2054 it("[[Call]] throws if the property can’t be set", () => {
2055 const obj = Object.freeze({ failure: undefined });
2056 assertThrows(() => setPropertyValues(obj, { failure: true }));
2057 });
2058
2059 it("[[Call]] returns the provided object", () => {
2060 const obj = {};
2061 assertStrictEquals(setPropertyValues(obj, { "": undefined }), obj);
2062 });
2063
2064 it("[[Construct]] throws an error", () => {
2065 assertThrows(() => new setPropertyValues(obj, { "": undefined }));
2066 });
2067
2068 describe(".length", () => {
2069 it("[[Get]] returns the correct length", () => {
2070 assertStrictEquals(setPropertyValues.length, 2);
2071 });
2072 });
2073
2074 describe(".name", () => {
2075 it("[[Get]] returns the correct name", () => {
2076 assertStrictEquals(setPropertyValues.name, "setPropertyValues");
2077 });
2078 });
2079 });
2080
2081 describe("setPrototype", () => {
2082 it("[[Call]] sets object prototypes", () => {
2083 const obj = {};
2084 const proto = {};
2085 setPrototype(obj, proto);
2086 assertStrictEquals(Object.getPrototypeOf(obj), proto);
2087 });
2088
2089 it("[[Call]] sets null prototypes", () => {
2090 const obj = {};
2091 setPrototype(obj, null);
2092 assertStrictEquals(Object.getPrototypeOf(obj), null);
2093 });
2094
2095 it("[[Call]] can set coercible primitives to their same prototype", () => {
2096 setPrototype(1, Number.prototype);
2097 setPrototype(Symbol(), Symbol.prototype);
2098 });
2099
2100 it("[[Call]] throws when setting coercible primitives to a different prototype", () => {
2101 assertThrows(() => setPrototype(1, Object.prototype));
2102 assertThrows(() => setPrototype(Symbol(), Object.prototype));
2103 });
2104
2105 it("[[Call]] throws for null and undefined", () => {
2106 assertThrows(() => setPrototype(null, Object.prototype));
2107 assertThrows(() => setPrototype(undefined, Object.prototype));
2108 });
2109
2110 it("[[Call]] returns the provided value", () => {
2111 const obj = {};
2112 assertStrictEquals(setPrototype(obj, null), obj);
2113 assertStrictEquals(setPrototype(1, Number.prototype), 1);
2114 });
2115
2116 it("[[Construct]] throws an error", () => {
2117 assertThrows(() => new setPrototype({}, null));
2118 });
2119
2120 describe(".length", () => {
2121 it("[[Get]] returns the correct length", () => {
2122 assertStrictEquals(setPrototype.length, 2);
2123 });
2124 });
2125
2126 describe(".name", () => {
2127 it("[[Get]] returns the correct name", () => {
2128 assertStrictEquals(setPrototype.name, "setPrototype");
2129 });
2130 });
2131 });
2132
2133 describe("toObject", () => {
2134 it("returns the input for objects", () => {
2135 const obj = {};
2136 assertStrictEquals(toObject(obj), obj);
2137 });
2138
2139 it("throws for nullish values", () => {
2140 assertThrows(() => toObject(null));
2141 assertThrows(() => toObject(void {}));
2142 });
2143
2144 it("returns a wrapper object for other primitives", () => {
2145 const sym = Symbol();
2146 assertStrictEquals(typeof toObject(sym), "object");
2147 assertStrictEquals(toObject(sym).valueOf(), sym);
2148 });
2149
2150 it("[[Construct]] throws an error", () => {
2151 assertThrows(() => new toObject({}));
2152 });
2153
2154 describe(".length", () => {
2155 it("[[Get]] returns the correct length", () => {
2156 assertStrictEquals(toObject.length, 1);
2157 });
2158 });
2159
2160 describe(".name", () => {
2161 it("[[Get]] returns the correct name", () => {
2162 assertStrictEquals(toObject.name, "toObject");
2163 });
2164 });
2165 });
2166
2167 describe("toPropertyKey", () => {
2168 it("returns a string or symbol", () => {
2169 const sym = Symbol();
2170 assertStrictEquals(toPropertyKey(sym), sym);
2171 assertStrictEquals(
2172 toPropertyKey(new String("success")),
2173 "success",
2174 );
2175 });
2176
2177 it("favours the `toString` representation", () => {
2178 assertStrictEquals(
2179 toPropertyKey({
2180 toString() {
2181 return "success";
2182 },
2183 valueOf() {
2184 return "failure";
2185 },
2186 }),
2187 "success",
2188 );
2189 });
2190
2191 it("[[Construct]] throws an error", () => {
2192 assertThrows(() => new toPropertyKey(""));
2193 });
2194
2195 describe(".length", () => {
2196 it("[[Get]] returns the correct length", () => {
2197 assertStrictEquals(toPropertyKey.length, 1);
2198 });
2199 });
2200
2201 describe(".name", () => {
2202 it("[[Get]] returns the correct name", () => {
2203 assertStrictEquals(toPropertyKey.name, "toPropertyKey");
2204 });
2205 });
2206 });
This page took 0.317137 seconds and 5 git commands to generate.