]>
Lady’s Gitweb - Pisces/blob - object.test.js
2b6cbb8163a43d749199baecde1fa2022fee98b2
1 // ♓🌟 Piscēs ∷ object.test.js
2 // ====================================================================
4 // Copyright © 2022 Lady [@ Lady’s Computer].
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/>.
20 } from "./dev-deps.js";
32 describe("LazyLoader", () => {
33 const symbol
= Symbol();
35 const etaoinMethod
= spy(() => "success");
36 const shrdluMethod
= spy(() => "success");
37 const cmfwypMethod
= spy(() => "success");
38 const vbgkqjMethod
= spy(() => "success");
39 const methodsObject
= Object
.create(
69 xz
fiflffffi: { configurable
: true, enumerable
: false, set(_
) {} },
79 it("[[Construct]] creates a new object which inherits from the correct prototype", () => {
81 Object
.getPrototypeOf(new LazyLoader(methodsObject
)),
86 it("[[Construct]] creates a new object with the desired properties", () => {
88 Reflect
.ownKeys(new LazyLoader(methodsObject
)),
89 ["etaoin", "shrdlu", "cmfwyp", "vbgkqj", "xzfiflffffi", symbol
],
93 it("[[Construct]] creates a new object with configurable properties", () => {
97 for (const key
of Reflect
.ownKeys(ll
)) {
100 Object
.getOwnPropertyDescriptor(ll
, key
).configurable
,
103 }(new LazyLoader(methodsObject
)),
116 it("[[Construct]] creates a new object with the correct enumerability", () => {
120 for (const key
of Reflect
.ownKeys(ll
)) {
123 Object
.getOwnPropertyDescriptor(ll
, key
).enumerable
,
126 }(new LazyLoader(methodsObject
)),
139 it("[[Construct]] creates a new object with defined getters", () => {
143 for (const key
of Reflect
.ownKeys(ll
)) {
146 Object
.getOwnPropertyDescriptor(ll
, key
).get !== void {},
149 }(new LazyLoader(methodsObject
)),
162 it("[[Construct]] creates a new object with defined setters for writable properties only", () => {
166 for (const key
of Reflect
.ownKeys(ll
)) {
169 Object
.getOwnPropertyDescriptor(ll
, key
).set !== void {},
172 }(new LazyLoader(methodsObject
)),
185 describe("[[Construct]] creates a new object with correct getter behaviour", () => {
186 const ll
= new LazyLoader(methodsObject
);
189 Object
.getOwnPropertyDescriptor(ll
, "etaoin"),
197 assertSpyCalls(etaoinMethod
, 1);
198 assertSpyCall(etaoinMethod
, 0, {
205 Object
.getOwnPropertyDescriptor(ll
, "shrdlu"),
213 assertSpyCalls(shrdluMethod
, 1);
214 assertSpyCall(shrdluMethod
, 0, {
221 Object
.getOwnPropertyDescriptor(ll
, "cmfwyp"),
229 assertSpyCalls(cmfwypMethod
, 1);
230 assertSpyCall(cmfwypMethod
, 0, {
237 Object
.getOwnPropertyDescriptor(ll
, "vbgkqj"),
245 assertSpyCalls(vbgkqjMethod
, 1);
246 assertSpyCall(vbgkqjMethod
, 0, {
251 assertThrows(() => ll
.xz
fiflffffi);
252 assertThrows(() => ll
[symbol
]);
255 describe("[[Construct]] creates a new object with correct setter behaviour", () => {
256 const ll
= new LazyLoader(methodsObject
);
257 ll
[symbol
] = "success";
259 Object
.getOwnPropertyDescriptor(ll
, symbol
),
270 describe("PropertyDescriptor", () => {
271 it("[[Construct]] creates a new PropertyDescriptor", () => {
273 Object
.getPrototypeOf(new PropertyDescriptor({})),
274 PropertyDescriptor
.prototype,
278 it("[[Construct]] throws for primitives", () => {
279 assertThrows(() => new PropertyDescriptor("failure"));
282 describe("::complete", () => {
283 it("[[Call]] completes a generic descriptor", () => {
285 PropertyDescriptor
.prototype.complete
.call(desc
);
294 it("[[Call]] completes a data descriptor", () => {
295 const desc
= { value
: undefined };
296 PropertyDescriptor
.prototype.complete
.call(desc
);
305 it("[[Call]] completes an accessor descriptor", () => {
306 const desc
= { get: undefined };
307 PropertyDescriptor
.prototype.complete
.call(desc
);
317 describe("::isAccessorDescriptor", () => {
318 it("[[Get]] returns false for a generic descriptor", () => {
321 PropertyDescriptor
.prototype,
322 "isAccessorDescriptor",
329 it("[[Get]] returns false for a data descriptor", () => {
332 PropertyDescriptor
.prototype,
333 "isAccessorDescriptor",
334 { value
: undefined },
340 it("[[Get]] returns true for an accessor descriptor", () => {
343 PropertyDescriptor
.prototype,
344 "isAccessorDescriptor",
352 describe("::isDataDescriptor", () => {
353 it("[[Get]] returns false for a generic descriptor", () => {
356 PropertyDescriptor
.prototype,
364 it("[[Get]] returns true for a data descriptor", () => {
367 PropertyDescriptor
.prototype,
369 { value
: undefined },
375 it("[[Get]] returns false for an accessor descriptor", () => {
378 PropertyDescriptor
.prototype,
387 describe("::isFullyPopulated", () => {
388 it("[[Get]] returns false for a generic descriptor", () => {
391 PropertyDescriptor
.prototype,
399 it("[[Get]] returns false for a non‐fully‐populated data descriptor", () => {
402 PropertyDescriptor
.prototype,
404 { value
: undefined },
410 it("[[Get]] returns true for a fully‐populated data descriptor", () => {
412 Reflect
.get(PropertyDescriptor
.prototype, "isFullyPopulated", {
422 it("[[Get]] returns false for a non‐fully‐populated accessor descriptor", () => {
425 PropertyDescriptor
.prototype,
433 it("[[Get]] returns true for a fully‐populated accessor descriptor", () => {
435 Reflect
.get(PropertyDescriptor
.prototype, "isFullyPopulated", {
446 describe("::isGenericDescriptor", () => {
447 it("[[Get]] returns true for a generic descriptor", () => {
450 PropertyDescriptor
.prototype,
451 "isGenericDescriptor",
458 it("[[Get]] returns true for a data descriptor", () => {
461 PropertyDescriptor
.prototype,
462 "isGenericDescriptor",
463 { value
: undefined },
469 it("[[Get]] returns false for an accessor descriptor", () => {
472 PropertyDescriptor
.prototype,
473 "isGenericDescriptor",
481 describe("~configurable", () => {
482 it("[[DefineOwnProperty]] coerces to a boolean", () => {
483 const desc
= new PropertyDescriptor({});
484 Object
.defineProperty(desc
, "configurable", {});
485 assertStrictEquals(desc
.configurable
, false);
488 it("[[DefineOwnProperty]] throws for accessor properties", () => {
489 const desc
= new PropertyDescriptor({});
491 Object
.defineProperty(desc
, "configurable", { get: undefined })
495 it("[[Set]] coerces to a boolean", () => {
496 const desc
= new PropertyDescriptor({});
497 desc
.configurable
= undefined;
498 assertStrictEquals(desc
.configurable
, false);
501 it("[[Delete]] works", () => {
502 const desc
= new PropertyDescriptor({ configurable
: false });
503 delete desc
.configurable
;
504 assert(!("configurable" in desc
));
508 describe("~enumerable", () => {
509 it("[[DefineOwnProperty]] coerces to a boolean", () => {
510 const desc
= new PropertyDescriptor({});
511 Object
.defineProperty(desc
, "enumerable", {});
512 assertStrictEquals(desc
.enumerable
, false);
515 it("[[DefineOwnProperty]] throws for accessor properties", () => {
516 const desc
= new PropertyDescriptor({});
518 Object
.defineProperty(desc
, "enumerable", { get: undefined })
522 it("[[Set]] coerces to a boolean", () => {
523 const desc
= new PropertyDescriptor({});
524 desc
.enumerable
= undefined;
525 assertStrictEquals(desc
.enumerable
, false);
528 it("[[Delete]] works", () => {
529 const desc
= new PropertyDescriptor({ enumerable
: false });
530 delete desc
.enumerable
;
531 assert(!("enumerable" in desc
));
535 describe("~get", () => {
536 it("[[DefineOwnProperty]] works", () => {
537 const desc
= new PropertyDescriptor({});
538 Object
.defineProperty(desc
, "get", {});
539 assertStrictEquals(desc
.get, undefined);
542 it("[[DefineOwnProperty]] throws for accessor properties", () => {
543 const desc
= new PropertyDescriptor({});
545 Object
.defineProperty(desc
, "get", { get: undefined })
549 it("[[DefineOwnProperty]] throws if not callable or undefined", () => {
550 const desc
= new PropertyDescriptor({});
552 () => Object
.defineProperty(desc
, "get", { value
: null }),
556 it("[[DefineOwnProperty]] throws if a data property is defined", () => {
557 const desc
= new PropertyDescriptor({ value
: undefined });
558 assertThrows(() => Object
.defineProperty(desc
, "get", {}));
561 it("[[Set]] works", () => {
562 const desc
= new PropertyDescriptor({});
565 assertStrictEquals(desc
.get, fn
);
568 it("[[Set]] throws if not callable or undefined", () => {
569 const desc
= new PropertyDescriptor({});
570 assertThrows(() => desc
.get = null);
573 it("[[Set]] throws if a data property is defined", () => {
574 const desc
= new PropertyDescriptor({ value
: undefined });
575 assertThrows(() => desc
.get = undefined);
578 it("[[Delete]] works", () => {
579 const desc
= new PropertyDescriptor({ get: undefined });
581 assert(!("get" in desc
));
585 describe("~set", () => {
586 it("[[DefineOwnProperty]] works", () => {
587 const desc
= new PropertyDescriptor({});
588 Object
.defineProperty(desc
, "set", {});
589 assertStrictEquals(desc
.set, undefined);
592 it("[[DefineOwnProperty]] throws for accessor properties", () => {
593 const desc
= new PropertyDescriptor({});
595 Object
.defineProperty(desc
, "set", { get: undefined })
599 it("[[DefineOwnProperty]] throws if not callable or undefined", () => {
600 const desc
= new PropertyDescriptor({});
602 () => Object
.defineProperty(desc
, "set", { value
: null }),
606 it("[[DefineOwnProperty]] throws if a data property is defined", () => {
607 const desc
= new PropertyDescriptor({ value
: undefined });
608 assertThrows(() => Object
.defineProperty(desc
, "set", {}));
611 it("[[Set]] works", () => {
612 const desc
= new PropertyDescriptor({});
613 const fn
= (_
) => {};
615 assertStrictEquals(desc
.set, fn
);
618 it("[[Set]] throws if not callable or undefined", () => {
619 const desc
= new PropertyDescriptor({});
620 assertThrows(() => desc
.set = null);
623 it("[[Set]] throws if a data property is defined", () => {
624 const desc
= new PropertyDescriptor({ value
: undefined });
625 assertThrows(() => desc
.set = undefined);
628 it("[[Delete]] works", () => {
629 const desc
= new PropertyDescriptor({ set: undefined });
631 assert(!("set" in desc
));
635 describe("~value", () => {
636 it("[[DefineOwnProperty]] works", () => {
637 const desc
= new PropertyDescriptor({});
638 Object
.defineProperty(desc
, "value", {});
639 assertStrictEquals(desc
.value
, undefined);
642 it("[[DefineOwnProperty]] throws for accessor properties", () => {
643 const desc
= new PropertyDescriptor({});
645 Object
.defineProperty(desc
, "value", { get: undefined })
649 it("[[DefineOwnProperty]] throws if an accessor property is defined", () => {
650 const desc
= new PropertyDescriptor({ get: undefined });
651 assertThrows(() => Object
.defineProperty(desc
, "value", {}));
654 it("[[Set]] works", () => {
655 const desc
= new PropertyDescriptor({});
656 desc
.value
= "success";
657 assertStrictEquals(desc
.value
, "success");
660 it("[[Set]] throws if an accessor property is defined", () => {
661 const desc
= new PropertyDescriptor({ get: undefined });
662 assertThrows(() => desc
.value
= null);
665 it("[[Delete]] works", () => {
666 const desc
= new PropertyDescriptor({ value
: undefined });
668 assert(!("value" in desc
));
672 describe("~writable", () => {
673 it("[[DefineOwnProperty]] coerces to a boolean", () => {
674 const desc
= new PropertyDescriptor({});
675 Object
.defineProperty(desc
, "writable", {});
676 assertStrictEquals(desc
.writable
, false);
679 it("[[DefineOwnProperty]] throws for accessor properties", () => {
680 const desc
= new PropertyDescriptor({});
682 Object
.defineProperty(desc
, "writable", { get: undefined })
686 it("[[DefineOwnProperty]] throws if an accessor property is defined", () => {
687 const desc
= new PropertyDescriptor({ get: undefined });
688 assertThrows(() => Object
.defineProperty(desc
, "writable", {}));
691 it("[[Set]] coerces to a boolean", () => {
692 const desc
= new PropertyDescriptor({});
693 desc
.writable
= undefined;
694 assertStrictEquals(desc
.writable
, false);
697 it("[[Set]] throws if an accessor property is defined", () => {
698 const desc
= new PropertyDescriptor({ get: undefined });
699 assertThrows(() => desc
.writable
= false);
702 it("[[Delete]] works", () => {
703 const desc
= new PropertyDescriptor({ writable
: false });
704 delete desc
.writable
;
705 assert(!("writable" in desc
));
710 describe("defineOwnProperties", () => {
711 it("[[Call]] defines properties from the provided objects", () => {
713 defineOwnProperties(obj
, {
717 assert("etaoin" in obj
);
718 assert("shrdlu" in obj
);
719 assert("cmfwyp" in obj
);
722 it("[[Call]] overrides earlier declarations with later ones", () => {
723 const obj
= { etaoin
: undefined };
724 defineOwnProperties(obj
, {
725 etaoin
: { value
: "failure" },
727 etaoin
: { value
: "success" },
729 assertStrictEquals(obj
.etaoin
, "success");
732 it("[[Call]] returns the provided object", () => {
734 assertStrictEquals(defineOwnProperties(obj
), obj
);
738 describe("deleteOwnProperty", () => {
739 it("[[Call]] deletes the provided property on the provided object", () => {
740 const obj
= { failure
: undefined };
741 deleteOwnProperty(obj
, "failure");
742 assert(!("failure" in obj
));
745 it("[[Call]] does nothing if the property doesn’t exist", () => {
746 const obj
= Object
.freeze({});
747 deleteOwnProperty(obj
, "failure");
748 assert(!("failure" in obj
));
751 it("[[Call]] throws if the property can’t be deleted", () => {
752 const obj
= Object
.seal({ failure
: undefined });
753 assertThrows(() => deleteOwnProperty(obj
, "failure"));
756 it("[[Call]] returns the provided object", () => {
758 assertStrictEquals(deleteOwnProperty(obj
, ""), obj
);
762 describe("frozenCopy", () => {
763 it("[[Call]] returns a frozen object", () => {
766 frozenCopy(Object
.create(null), {
783 it("[[Call]] ignores non·enumerable properties", () => {
786 Object
.create(null, {
787 data
: { value
: undefined },
788 accessor
: { get: undefined },
795 it("[[Call]] preserves accessor properties", () => {
823 Object
.getOwnPropertyDescriptors(
824 frozenCopy(Object
.create(null, properties
)),
830 it("[[Call]] does not copy properties on the prototype", () => {
833 frozenCopy(Object
.create({ failure
: undefined }), {
839 accessor
: { configurable
: true, get: undefined },
844 it("[[Call]] uses the species of the constructor", () => {
845 const species
= { prototype: {} };
847 Object
.getPrototypeOf(
848 frozenCopy({}, { [Symbol
.species
]: species
}),
854 it("[[Call]] uses constructor if no species is defined", () => {
855 const constructor = { [Symbol
.species
]: null, prototype: {} };
857 Object
.getPrototypeOf(frozenCopy({}, constructor)),
858 constructor.prototype,
862 it("[[Call]] uses the constructor on the object if none is provided", () => {
863 const constructor = { [Symbol
.species
]: null, prototype: {} };
865 Object
.getPrototypeOf(frozenCopy({ constructor })),
866 constructor.prototype,
870 it("[[Call]] allows a null constructor", () => {
872 Object
.getPrototypeOf(frozenCopy({}, null)),
878 describe("setPropertyValue", () => {
879 it("[[Call]] sets the provided property on the provided object", () => {
881 setPropertyValue(obj
, "success", true);
882 assertStrictEquals(obj
.success
, true);
885 it("[[Call]] calls setters", () => {
886 const setter
= spy((_
) => {});
887 const obj
= Object
.create(null, { success
: { set: setter
} });
888 setPropertyValue(obj
, "success", true);
889 assertSpyCalls(setter
, 1);
890 assertSpyCall(setter
, 0, {
896 it("[[Call]] walks the prototype chain", () => {
897 const setter
= spy((_
) => {});
898 const obj
= Object
.create(
899 Object
.create(null, { success
: { set: setter
} }),
901 setPropertyValue(obj
, "success", true);
902 assertSpyCalls(setter
, 1);
903 assertSpyCall(setter
, 0, {
909 it("[[Call]] uses the provided receiver", () => {
910 const setter
= spy((_
) => {});
911 const obj
= Object
.create(null, { success
: { set: setter
} });
913 setPropertyValue(obj
, "success", true, receiver
);
914 assertSpyCalls(setter
, 1);
915 assertSpyCall(setter
, 0, {
921 it("[[Call]] throws if the property can’t be set", () => {
922 const obj
= Object
.freeze({ failure
: undefined });
923 assertThrows(() => setPropertyValue(obj
, "failure", true));
926 it("[[Call]] returns the provided object", () => {
928 assertStrictEquals(setPropertyValue(obj
, "", undefined), obj
);
932 describe("toObject", () => {
933 it("returns the input for objects", () => {
935 assertStrictEquals(toObject(obj
), obj
);
938 it("returns a new object for nullish values", () => {
939 assertEquals(toObject(null), {});
940 assertEquals(toObject(void {}), {});
943 it("returns a wrapper object for other primitives", () => {
944 const sym
= Symbol();
945 assertStrictEquals(typeof toObject(sym
), "object");
946 assertStrictEquals(toObject(sym
).valueOf(), sym
);
950 describe("toPropertyKey", () => {
951 it("returns a string or symbol", () => {
952 const sym
= Symbol();
953 assertStrictEquals(toPropertyKey(sym
), sym
);
955 toPropertyKey(new String("success")),
960 it("favours the `toString` representation", () => {
This page took 0.132547 seconds and 3 git commands to generate.