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