]> Lady’s Gitweb - Pisces/blob - object.js
83519fd8b0f9a9f0a59517631c30be4fbfa97453
[Pisces] / object.js
1 // ♓🌟 Piscēs ∷ object.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 bind,
12 call,
13 createArrowFunction,
14 toFunctionName,
15 } from "./function.js";
16 import { ITERATOR, SPECIES, toPrimitive, type } from "./value.js";
17
18 /**
19 * An object whose properties are lazy‐loaded from the methods on the
20 * own properties of the provided object.
21 *
22 * This is useful when you are looking to reference properties on
23 * objects which, due to module dependency graphs, cannot be guaranteed
24 * to have been initialized yet.
25 *
26 * The resulting properties will have the same attributes (regarding
27 * configurability, enumerability, and writability) as the
28 * corresponding properties on the methods object. If a property is
29 * marked as writable, the method will never be called if it is set
30 * before it is gotten. By necessity, the resulting properties are all
31 * configurable before they are accessed for the first time.
32 *
33 * Methods will be called with the resulting object as their this
34 * value.
35 *
36 * `LazyLoader` objects have the same prototype as the passed methods
37 * object.
38 */
39 export class LazyLoader extends null {
40 /**
41 * Constructs a new `LazyLoader` object.
42 *
43 * ☡ This function throws if the provided value is not an object.
44 */
45 constructor(loadMethods) {
46 if (type(loadMethods) !== "object") {
47 // The provided value is not an object; throw an error.
48 throw new TypeError(
49 `Piscēs: Cannot construct LazyLoader: Provided argument is not an object: ${loadMethods}.`,
50 );
51 } else {
52 // The provided value is an object; process it and build the
53 // result.
54 const result = objectCreate(getPrototype(loadMethods));
55 const methodKeys = getOwnPropertyKeys(loadMethods);
56 for (let index = 0; index < methodKeys.length; ++index) {
57 // Iterate over the property keys of the provided object and
58 // define getters and setters appropriately on the result.
59 const methodKey = methodKeys[index];
60 const { configurable, enumerable, writable } =
61 getOwnPropertyDescriptor(loadMethods, methodKey);
62 defineOwnProperty(result, methodKey, {
63 configurable: true,
64 enumerable,
65 get: defineOwnProperty(
66 () => {
67 const value = call(loadMethods[methodKey], result, []);
68 defineOwnProperty(result, methodKey, {
69 configurable,
70 enumerable,
71 value,
72 writable,
73 });
74 return value;
75 },
76 "name",
77 { value: toFunctionName(methodKey, "get") },
78 ),
79 set: writable
80 ? defineOwnProperty(
81 ($) =>
82 defineOwnProperty(result, methodKey, {
83 configurable,
84 enumerable,
85 value: $,
86 writable,
87 }),
88 "name",
89 { value: toFunctionName(methodKey, "set") },
90 )
91 : void {},
92 });
93 }
94 return result;
95 }
96 }
97 }
98
99 /**
100 * A property descriptor object.
101 *
102 * Actually constructing a property descriptor object using this class
103 * is only necessary if you need strict guarantees about the types of
104 * its properties; the resulting object is proxied to ensure the types
105 * match what one would expect from composing FromPropertyDescriptor
106 * and ToPropertyDescriptor in the Ecmascript specification.
107 *
108 * Otherwise, the instance properties and methods are generic.
109 */
110 export const { PropertyDescriptor } = (() => {
111 class PropertyDescriptor extends null {
112 /**
113 * Constructs a new property descriptor object from the provided
114 * object.
115 *
116 * The resulting object is proxied to enforce types (for example,
117 * its `.enumerable` property, if defined, will always be a
118 * boolean).
119 */
120 constructor(O) {
121 if (type(O) !== "object") {
122 // The provided value is not an object.
123 throw new TypeError(
124 `Piscēs: Cannot convert primitive to property descriptor: ${O}.`,
125 );
126 } else {
127 // The provided value is an object.
128 const desc = objectCreate(propertyDescriptorPrototype);
129 if ("enumerable" in O) {
130 // An enumerable property is specified.
131 desc.enumerable = !!O.enumerable;
132 } else {
133 // An enumerable property is not specified.
134 /* do nothing */
135 }
136 if ("configurable" in O) {
137 // A configurable property is specified.
138 desc.configurable = !!O.configurable;
139 } else {
140 // A configurable property is not specified.
141 /* do nothing */
142 }
143 if ("value" in O) {
144 // A value property is specified.
145 desc.value = O.value;
146 } else {
147 // A value property is not specified.
148 /* do nothing */
149 }
150 if ("writable" in O) {
151 // A writable property is specified.
152 desc.writable = !!O.writable;
153 } else {
154 // A writable property is not specified.
155 /* do nothing */
156 }
157 if ("get" in O) {
158 // A get property is specified.
159 const getter = O.get;
160 if (getter !== undefined && typeof getter !== "function") {
161 // The getter is not callable.
162 throw new TypeError("Piscēs: Getters must be callable.");
163 } else {
164 // The getter is callable.
165 desc.get = getter;
166 }
167 } else {
168 // A get property is not specified.
169 /* do nothing */
170 }
171 if ("set" in O) {
172 // A set property is specified.
173 const setter = O.set;
174 if (setter !== undefined && typeof setter !== "function") {
175 // The setter is not callable.
176 throw new TypeError("Piscēs: Setters must be callable.");
177 } else {
178 // The setter is callable.
179 desc.set = setter;
180 }
181 } else {
182 // A set property is not specified.
183 /* do nothing */
184 }
185 if (
186 ("get" in desc || "set" in desc) &&
187 ("value" in desc || "writable" in desc)
188 ) {
189 // Both accessor and data attributes have been defined.
190 throw new TypeError(
191 "Piscēs: Property descriptors cannot specify both accessor and data attributes.",
192 );
193 } else {
194 // The property descriptor is valid.
195 return new Proxy(desc, propertyDescriptorProxyHandler);
196 }
197 }
198 }
199
200 /**
201 * Completes this property descriptor by setting missing values to
202 * their defaults.
203 *
204 * This method modifies this object and returns undefined.
205 */
206 complete() {
207 if (this !== undefined && !("get" in this || "set" in this)) {
208 // This is a generic or data descriptor.
209 if (!("value" in this)) {
210 // `value` is not defined on this.
211 this.value = undefined;
212 } else {
213 // `value` is already defined on this.
214 /* do nothing */
215 }
216 if (!("writable" in this)) {
217 // `writable` is not defined on this.
218 this.writable = false;
219 } else {
220 // `writable` is already defined on this.
221 /* do nothing */
222 }
223 } else {
224 // This is not a generic or data descriptor.
225 if (!("get" in this)) {
226 // `get` is not defined on this.
227 this.get = undefined;
228 } else {
229 // `get` is already defined on this.
230 /* do nothing */
231 }
232 if (!("set" in this)) {
233 // `set` is not defined on this.
234 this.set = undefined;
235 } else {
236 // `set` is already defined on this.
237 /* do nothing */
238 }
239 }
240 if (!("enumerable" in this)) {
241 // `enumerable` is not defined on this.
242 this.enumerable = false;
243 } else {
244 // `enumerable` is already defined on this.
245 /* do nothing */
246 }
247 if (!("configurable" in this)) {
248 // `configurable` is not defined on this.
249 this.configurable = false;
250 } else {
251 // `configurable` is already defined on this.
252 /* do nothing */
253 }
254 }
255
256 /** Gets whether this is an accessor descrtiptor. */
257 get isAccessorDescriptor() {
258 return this !== undefined && ("get" in this || "set" in this);
259 }
260
261 /** Gets whether this is a data descrtiptor. */
262 get isDataDescriptor() {
263 return this !== undefined &&
264 ("value" in this || "writable" in this);
265 }
266
267 /** Gets whether this is a fully‐populated property descriptor. */
268 get isFullyPopulated() {
269 return this !== undefined &&
270 ("value" in this && "writable" in this ||
271 "get" in this && "set" in this) &&
272 "enumerable" in this && "configurable" in this;
273 }
274
275 /**
276 * Gets whether this is a generic (not accessor or data)
277 * descrtiptor.
278 */
279 get isGenericDescriptor() {
280 return this !== undefined &&
281 !("get" in this || "set" in this || "value" in this ||
282 "writable" in this);
283 }
284 }
285
286 const coercePropertyDescriptorValue = (P, V) => {
287 switch (P) {
288 case "configurable":
289 case "enumerable":
290 case "writable":
291 return !!V;
292 case "value":
293 return V;
294 case "get":
295 if (V !== undefined && typeof V !== "function") {
296 throw new TypeError(
297 "Piscēs: Getters must be callable.",
298 );
299 } else {
300 return V;
301 }
302 case "set":
303 if (V !== undefined && typeof V !== "function") {
304 throw new TypeError(
305 "Piscēs: Setters must be callable.",
306 );
307 } else {
308 return V;
309 }
310 default:
311 return V;
312 }
313 };
314
315 const {
316 prototype: propertyDescriptorPrototype,
317 } = PropertyDescriptor;
318
319 const propertyDescriptorProxyHandler = Object.assign(
320 Object.create(null),
321 {
322 defineProperty(O, P, Desc) {
323 if (
324 P === "configurable" || P === "enumerable" ||
325 P === "writable" || P === "value" ||
326 P === "get" || P === "set"
327 ) {
328 // P is a property descriptor attribute.
329 const desc = new PropertyDescriptor(Desc);
330 if ("get" in desc || "set" in desc) {
331 // Desc is an accessor property descriptor.
332 throw new TypeError(
333 "Piscēs: Property descriptor attributes must be data properties.",
334 );
335 } else if ("value" in desc || !(P in O)) {
336 // Desc has a value or P does not already exist on O.
337 desc.value = coercePropertyDescriptorValue(P, desc.value);
338 } else {
339 // Desc is not an accessor property descriptor and has no
340 // value.
341 /* do nothing */
342 }
343 const isAccessorDescriptor = "get" === P || "set" === P ||
344 "get" in O || "set" in O;
345 const isDataDescriptor = "value" === P || "writable" === P ||
346 "value" in O || "writable" in O;
347 if (isAccessorDescriptor && isDataDescriptor) {
348 // Both accessor and data attributes will be present on O
349 // after defining P.
350 throw new TypeError(
351 "Piscēs: Property descriptors cannot specify both accessor and data attributes.",
352 );
353 } else {
354 // P can be safely defined on O.
355 return defineOwnProperty(O, P, desc);
356 }
357 } else {
358 // P is not a property descriptor attribute.
359 return defineOwnProperty(O, P, Desc);
360 }
361 },
362 set(O, P, V, Receiver) {
363 if (
364 P === "configurable" || P === "enumerable" ||
365 P === "writable" || P === "value" ||
366 P === "get" || P === "set"
367 ) {
368 // P is a property descriptor attribute.
369 const newValue = coercePropertyDescriptorValue(P, V);
370 const isAccessorDescriptor = "get" === P || "set" === P ||
371 "get" in O || "set" in O;
372 const isDataDescriptor = "value" === P || "writable" === P ||
373 "value" in O || "writable" in O;
374 if (isAccessorDescriptor && isDataDescriptor) {
375 // Both accessor and data attributes will be present on O
376 // after defining P.
377 throw new TypeError(
378 "Piscēs: Property descriptors cannot specify both accessor and data attributes.",
379 );
380 } else {
381 // P can be safely defined on O.
382 //
383 // ☡ Receiver will be the *proxied* object, so passing it
384 // through to setPropertyValue here would produce an
385 // infinite loop.
386 //
387 // ☡ This has implications on objects with a proxied
388 // PropertyDescriptor in their prototype.
389 return setPropertyValue(O, P, newValue, O);
390 }
391 } else {
392 return setPropertyValue(O, P, V, Receiver);
393 }
394 },
395 setPrototypeOf(O, V) {
396 if (V !== propertyDescriptorPrototype) {
397 // V is not the property descriptor prototype.
398 return false;
399 } else {
400 // V is the property descriptor prototype.
401 return setPrototype(O, V);
402 }
403 },
404 },
405 );
406
407 return { PropertyDescriptor };
408 })();
409
410 /**
411 * Defines an own property on the provided object on the provided
412 * property key using the provided property descriptor.
413 *
414 * ※ This is effectively an alias for `Object.defineProperty`.
415 */
416 export const defineOwnProperty = createArrowFunction(
417 Object.defineProperty,
418 { name: "defineOwnProperty" },
419 );
420
421 export const {
422 /**
423 * Defines own properties on the provided object using the
424 * descriptors on the enumerable own properties of the provided
425 * additional objects.
426 *
427 * ※ This differs from `Object.defineProperties` in that it can take
428 * multiple source objects.
429 */
430 defineOwnProperties,
431
432 /**
433 * Returns a new frozen shallow copy of the enumerable own properties
434 * of the provided object, according to the following rules :—
435 *
436 * - For data properties, create a nonconfigurable, nonwritable
437 * property with the same value.
438 *
439 * - For accessor properties, create a nonconfigurable accessor
440 * property with the same getter *and* setter.
441 *
442 * The prototype for the resulting object will be taken from the
443 * `.prototype` property of the provided constructor, or the
444 * `.prototype` of the `.constructor` of the provided object if the
445 * provided constructor is undefined. If the used constructor has a
446 * nonnullish `.[Symbol.species]`, that will be used instead. If the
447 * used constructor or species is nullish or does not have a
448 * `.prototype` property, the prototype is set to null.
449 *
450 * ※ The prototype of the provided object itself is ignored.
451 */
452 frozenCopy,
453
454 /**
455 * Returns whether the provided object is frozen.
456 *
457 * ※ This function returns false for nonobjects.
458 *
459 * ※ This is effectively an alias for `!Object.isFrozen`.
460 */
461 isUnfrozenObject,
462
463 /**
464 * Returns whether the provided object is sealed.
465 *
466 * ※ This function returns false for nonobjects.
467 *
468 * ※ This is effectively an alias for `!Object.isSealed`.
469 */
470 isUnsealedObject,
471
472 /**
473 * Sets the prototype of the provided object to the provided value
474 * and returns the object.
475 *
476 * ※ This is effectively an alias for `Object.setPrototypeOf`.
477 */
478 setPrototype,
479
480 /**
481 * Returns the provided value converted to an object.
482 *
483 * Existing objects are returned with no modification.
484 *
485 * ☡ This function throws if its argument is null or undefined.
486 */
487 toObject,
488 } = (() => {
489 const createObject = Object;
490 const {
491 create,
492 defineProperties,
493 getPrototypeOf,
494 isFrozen,
495 isSealed,
496 setPrototypeOf,
497 } = Object;
498 const { [ITERATOR]: arrayIterator } = Array.prototype;
499 const { next: arrayIteratorNext } = getPrototypeOf([][ITERATOR]());
500 const {
501 next: generatorIteratorNext,
502 } = getPrototypeOf(function* () {}.prototype);
503 const splatIterablePrototype = {
504 [ITERATOR]() {
505 return {
506 next: bind(
507 arrayIteratorNext,
508 call(arrayIterator, this.args, []),
509 [],
510 ),
511 };
512 },
513 };
514 const splatIterable = ($) =>
515 create(splatIterablePrototype, { args: { value: $ } });
516 const propertyDescriptorEntryIterablePrototype = {
517 [ITERATOR]() {
518 return {
519 next: bind(generatorIteratorNext, this.generator(), []),
520 };
521 },
522 };
523 const propertyDescriptorEntryIterable = ($) =>
524 create(propertyDescriptorEntryIterablePrototype, {
525 generator: { value: $ },
526 });
527
528 return {
529 defineOwnProperties: (O, ...sources) => {
530 for (const source of splatIterable(sources)) {
531 defineProperties(O, source);
532 }
533 return O;
534 },
535 frozenCopy: (O, constructor = O?.constructor) => {
536 if (O == null) {
537 // O is null or undefined.
538 throw new TypeError(
539 "Piscēs: Cannot copy properties of null or undefined.",
540 );
541 } else {
542 // O is not null or undefined.
543 //
544 // (If not provided, the constructor will be the value of
545 // getting the `.constructor` property of O.)
546 const species = constructor?.[SPECIES] ?? constructor;
547 return preventExtensions(
548 objectCreate(
549 species == null || !("prototype" in species)
550 ? null
551 : species.prototype,
552 objectFromEntries(
553 propertyDescriptorEntryIterable(function* () {
554 const ownPropertyKeys = getOwnPropertyKeys(O);
555 for (
556 let i = 0;
557 i < ownPropertyKeys.length;
558 ++i
559 ) {
560 const P = ownPropertyKeys[i];
561 const Desc = getOwnPropertyDescriptor(O, P);
562 if (Desc.enumerable) {
563 // P is an enumerable property.
564 yield [
565 P,
566 "get" in Desc || "set" in Desc
567 ? {
568 configurable: false,
569 enumerable: true,
570 get: Desc.get,
571 set: Desc.set,
572 }
573 : {
574 configurable: false,
575 enumerable: true,
576 value: Desc.value,
577 writable: false,
578 },
579 ];
580 } else {
581 // P is not an enumerable property.
582 /* do nothing */
583 }
584 }
585 }),
586 ),
587 ),
588 );
589 }
590 },
591 isUnfrozenObject: (O) => !isFrozen(O),
592 isUnsealedObject: (O) => !isSealed(O),
593 setPrototype: (O, proto) => {
594 const obj = toObject(O);
595 if (O === obj) {
596 // The provided value is an object; set its prototype normally.
597 return setPrototypeOf(O, proto);
598 } else {
599 // The provided value is not an object; attempt to set the
600 // prototype on a coerced version with extensions prevented,
601 // then return the provided value.
602 //
603 // This will throw if the given prototype does not match the
604 // existing one on the coerced object.
605 setPrototypeOf(preventExtensions(obj), proto);
606 return O;
607 }
608 },
609 toObject: ($) => {
610 if ($ == null) {
611 // The provided value is nullish; this is an error.
612 throw new TypeError(
613 `Piscēs: Cannot convert ${$} into an object.`,
614 );
615 } else {
616 // The provided value is not nullish; coerce it to an object.
617 return createObject($);
618 }
619 },
620 };
621 })();
622
623 export const {
624 /**
625 * Removes the provided property key from the provided object and
626 * returns the object.
627 *
628 * ※ This function differs from `Reflect.deleteProperty` and the
629 * `delete` operator in that it throws if the deletion is
630 * unsuccessful.
631 *
632 * ☡ This function throws if the first argument is not an object.
633 */
634 deleteOwnProperty,
635
636 /**
637 * Returns an array of property keys on the provided object.
638 *
639 * ※ This is effectively an alias for `Reflect.ownKeys`, except that
640 * it does not require that the argument be an object.
641 */
642 getOwnPropertyKeys,
643
644 /**
645 * Returns the value of the provided property key on the provided
646 * object.
647 *
648 * ※ This is effectively an alias for `Reflect.get`, except that it
649 * does not require that the argument be an object.
650 */
651 getPropertyValue,
652
653 /**
654 * Returns whether the provided property key exists on the provided
655 * object.
656 *
657 * ※ This is effectively an alias for `Reflect.has`, except that it
658 * does not require that the argument be an object.
659 *
660 * ※ This includes properties present on the prototype chain.
661 */
662 hasProperty,
663
664 /**
665 * Sets the provided property key to the provided value on the
666 * provided object and returns the object.
667 *
668 * ※ This function differs from `Reflect.set` in that it throws if
669 * the setting is unsuccessful.
670 *
671 * ☡ This function throws if the first argument is not an object.
672 */
673 setPropertyValue,
674 } = (() => {
675 const { deleteProperty, get, has, ownKeys, set } = Reflect;
676
677 return {
678 deleteOwnProperty: (O, P) => {
679 if (type(O) !== "object") {
680 throw new TypeError(
681 `Piscēs: Tried to set property but provided value was not an object: ${V}`,
682 );
683 } else if (!deleteProperty(O, P)) {
684 throw new TypeError(
685 `Piscēs: Tried to delete property from object but [[Delete]] returned false: ${P}`,
686 );
687 } else {
688 return O;
689 }
690 },
691 getOwnPropertyKeys: (O) => ownKeys(toObject(O)),
692 getPropertyValue: (O, P, Receiver = O) =>
693 get(toObject(O), P, Receiver),
694 hasProperty: (O, P) => has(toObject(O), P),
695 setPropertyValue: (O, P, V, Receiver = O) => {
696 if (type(O) !== "object") {
697 throw new TypeError(
698 `Piscēs: Tried to set property but provided value was not an object: ${V}`,
699 );
700 } else if (!set(O, P, V, Receiver)) {
701 throw new TypeError(
702 `Piscēs: Tried to set property on object but [[Set]] returned false: ${P}`,
703 );
704 } else {
705 return O;
706 }
707 },
708 };
709 })();
710
711 /**
712 * Marks the provided object as non·extensible and marks all its
713 * properties as nonconfigurable and (if data properties) nonwritable,
714 * and returns the object.
715 *
716 * ※ This is effectively an alias for `Object.freeze`.
717 */
718 export const freeze = createArrowFunction(Object.freeze);
719
720 /**
721 * Returns the function on the provided value at the provided property
722 * key.
723 *
724 * ☡ This function throws if the provided property key does not have an
725 * associated value which is callable.
726 */
727 export const getMethod = (V, P) => {
728 const func = getPropertyValue(V, P);
729 if (func == null) {
730 return undefined;
731 } else if (typeof func !== "function") {
732 throw new TypeError(`Piscēs: Method not callable: ${P}`);
733 } else {
734 return func;
735 }
736 };
737
738 /**
739 * Returns the property descriptor for the own property with the
740 * provided property key on the provided object, or null if none
741 * exists.
742 *
743 * ※ This is effectively an alias for
744 * `Object.getOwnPropertyDescriptor`.
745 */
746 export const getOwnPropertyDescriptor = createArrowFunction(
747 Object.getOwnPropertyDescriptor,
748 );
749
750 /**
751 * Returns the property descriptors for the own properties on the
752 * provided object.
753 *
754 * ※ This is effectively an alias for
755 * `Object.getOwnPropertyDescriptors`.
756 */
757 export const getOwnPropertyDescriptors = createArrowFunction(
758 Object.getOwnPropertyDescriptors,
759 );
760
761 /**
762 * Returns an array of string‐valued own property keys on the
763 * provided object.
764 *
765 * ☡ This includes both enumerable and non·enumerable properties.
766 *
767 * ※ This is effectively an alias for `Object.getOwnPropertyNames`.
768 */
769 export const getOwnPropertyStrings = createArrowFunction(
770 Object.getOwnPropertyNames,
771 { name: "getOwnPropertyStrings" },
772 );
773
774 /**
775 * Returns an array of symbol‐valued own property keys on the
776 * provided object.
777 *
778 * ☡ This includes both enumerable and non·enumerable properties.
779 *
780 * ※ This is effectively an alias for
781 * `Object.getOwnPropertySymbols`.
782 */
783 export const getOwnPropertySymbols = createArrowFunction(
784 Object.getOwnPropertySymbols,
785 );
786
787 /**
788 * Returns the prototype of the provided object.
789 *
790 * ※ This is effectively an alias for `Object.getPrototypeOf`.
791 */
792 export const getPrototype = createArrowFunction(
793 Object.getPrototypeOf,
794 { name: "getPrototype" },
795 );
796
797 /**
798 * Returns whether the provided object has an own property with the
799 * provided property key.
800 *
801 * ※ This is effectively an alias for `Object.hasOwn`.
802 */
803 export const hasOwnProperty = createArrowFunction(Object.hasOwn, {
804 name: "hasOwnProperty",
805 });
806
807 /**
808 * Returns whether the provided object is extensible.
809 *
810 * ※ This function returns false for nonobjects.
811 *
812 * ※ This is effectively an alias for `Object.isExtensible`.
813 */
814 export const isExtensibleObject = createArrowFunction(
815 Object.isExtensible,
816 { name: "isExtensibleObject" },
817 );
818
819 /**
820 * Returns an array of key~value pairs for the enumerable,
821 * string‐valued property keys on the provided object.
822 *
823 * ※ This is effectively an alias for `Object.entries`.
824 */
825 export const namedEntries = createArrowFunction(Object.entries, {
826 name: "namedEntries",
827 });
828
829 /**
830 * Returns an array of the enumerable, string‐valued property keys on
831 * the provided object.
832 *
833 * ※ This is effectively an alias for `Object.keys`.
834 */
835 export const namedKeys = createArrowFunction(Object.keys, {
836 name: "namedKeys",
837 });
838
839 /**
840 * Returns an array of property values for the enumerable,
841 * string‐valued property keys on the provided object.
842 *
843 * ※ This is effectively an alias for `Object.values`.
844 */
845 export const namedValues = createArrowFunction(Object.values, {
846 name: "namedValues",
847 });
848
849 /**
850 * Returns a new object with the provided prototype and property
851 * descriptors.
852 *
853 * ※ This is effectively an alias for `Object.create`.
854 */
855 export const objectCreate = createArrowFunction(Object.create, {
856 name: "objectCreate",
857 });
858
859 /**
860 * Returns a new object with the provided property keys and values.
861 *
862 * ※ This is effectively an alias for `Object.fromEntries`.
863 */
864 export const objectFromEntries = createArrowFunction(
865 Object.fromEntries,
866 { name: "objectFromEntries" },
867 );
868
869 /**
870 * Marks the provided object as non·extensible, and returns the
871 * object.
872 *
873 * ※ This is effectively an alias for `Object.preventExtensions`.
874 */
875 export const preventExtensions = createArrowFunction(
876 Object.preventExtensions,
877 );
878
879 /**
880 * Marks the provided object as non·extensible and marks all its
881 * properties as nonconfigurable, and returns the object.
882 *
883 * ※ This is effectively an alias for `Object.seal`.
884 */
885 export const seal = createArrowFunction(Object.seal);
886
887 /**
888 * Sets the values of the enumerable own properties of the provided
889 * additional objects on the provided object.
890 *
891 * ※ This is effectively an alias for `Object.assign`.
892 */
893 export const setPropertyValues = createArrowFunction(Object.assign, {
894 name: "setPropertyValues",
895 });
896
897 /**
898 * Returns the property key (symbol or string) corresponding to the
899 * provided value.
900 */
901 export const toPropertyKey = ($) => {
902 const key = toPrimitive($, "string");
903 return typeof key === "symbol" ? key : `${key}`;
904 };
This page took 0.138554 seconds and 3 git commands to generate.