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