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