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