X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/f6b84c13c5c539dbac4f4b9b530eeec95d683475..e1cb83c479df2a3e4a5e918867a135ff9dde8121:/object.js?ds=sidebyside
diff --git a/object.js b/object.js
index aa94bc5..d382b31 100644
--- a/object.js
+++ b/object.js
@@ -1,24 +1,29 @@
-// ♓🌟 Piscēs ∷ object.js
-// ====================================================================
-//
-// Copyright © 2022–2023 Lady [@ Lady’s Computer].
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at .
+// SPDX-FileCopyrightText: 2022, 2023, 2025 Lady
+// SPDX-License-Identifier: MPL-2.0
+/**
+ * ⁌ ♓🧩 Piscēs ∷ object.js
+ *
+ * Copyright © 2022–2023, 2025 Lady [@ Ladys Computer].
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at .
+ */
import {
IS_CONCAT_SPREADABLE,
isAccessorDescriptor,
+ isDataDescriptor,
SPECIES,
toFunctionName,
toLength,
- toPrimitive,
- toPropertyDescriptor,
type,
UNDEFINED,
} from "./value.js";
+const PISCĒS = "♓🧩 Piscēs";
+
+const createArray = Array;
const { isArray } = Array;
const object = Object;
const {
@@ -46,11 +51,13 @@ const {
const {
apply: call,
deleteProperty,
+ defineProperty: reflectDefineProperty,
get,
getOwnPropertyDescriptor: reflectGetOwnPropertyDescriptor,
has,
ownKeys,
set,
+ setPrototypeOf: reflectSetPrototypeOf,
} = Reflect;
/**
@@ -71,24 +78,25 @@ const {
* Methods will be called with the resulting object as their this
* value.
*
- * `LazyLoader` objects have the same prototype as the passed methods
+ * `LazyLoader´ objects have the same prototype as the passed methods
* object.
*/
export class LazyLoader extends null {
/**
- * Constructs a new `LazyLoader` object.
+ * Constructs a new `LazyLoader´ object.
*
* ☡ This function throws if the provided value is not an object.
*/
constructor(loadMethods) {
if (type(loadMethods) !== "object") {
- // The provided value is not an object; throw an error.
+ // The provided value is not an object; this is an error.
throw new TypeError(
- `Piscēs: Cannot construct LazyLoader: Provided argument is not an object: ${loadMethods}.`,
+ `${PISCĒS}: Cannot construct LazyLoader: Provided argument is not an object: ${loadMethods}.`,
);
} else {
- // The provided value is an object; process it and build the
- // result.
+ // The provided value is an object.
+ //
+ // Process it and build the result.
const result = create(getPrototypeOf(loadMethods));
const methodKeys = ownKeys(loadMethods);
for (let index = 0; index < methodKeys.length; ++index) {
@@ -186,7 +194,7 @@ export const defineOwnNonenumerableDataProperty = (O, P, V) =>
* Defines an own property on the provided object on the provided
* property key using the provided property descriptor.
*
- * ※ This is effectively an alias for `Object.defineProperty`.
+ * ※ This is effectively an alias for `Object.defineProperty´.
*/
export const defineOwnProperty = (O, P, Desc) =>
defineProperty(O, P, Desc);
@@ -195,12 +203,14 @@ export const defineOwnProperty = (O, P, Desc) =>
* Defines own properties on the provided object using the descriptors
* on the enumerable own properties of the provided additional objects.
*
- * ※ This differs from `Object.defineProperties` in that it can take
- * multiple source objects.
+ * ※ This function differs from `Object.defineProperties´ in that it
+ * can take multiple source objects.
*/
export const defineOwnProperties = (O, ...sources) => {
const { length } = sources;
for (let k = 0; k < length; ++k) {
+ // Iterate over each source and define the appropriate properties
+ // on the provided object.
defineProperties(O, sources[k]);
}
return O;
@@ -210,22 +220,28 @@ export const defineOwnProperties = (O, ...sources) => {
* Removes the provided property key from the provided object and
* returns the object.
*
- * ※ This function differs from `Reflect.deleteProperty` and the
- * `delete` operator in that it throws if the deletion is
+ * ※ This function differs from `Reflect.deleteProperty´ and the
+ * `delete´ operator in that it throws if the deletion is
* unsuccessful.
*
* ☡ This function throws if the first argument is not an object.
*/
export const deleteOwnProperty = (O, P) => {
if (type(O) !== "object") {
+ // The provided value is not an object; this is an error.
throw new TypeError(
- `Piscēs: Tried to set property but provided value was not an object: ${V}`,
+ `${PISCĒS}: Tried to set property but provided value was not an object: ${V}`,
);
} else if (!deleteProperty(O, P)) {
+ // The provided property could not be deleted on the provided
+ // value; this is an error.
throw new TypeError(
- `Piscēs: Tried to delete property from object but [[Delete]] returned false: ${P}`,
+ `${PISCĒS}: Tried to delete property from object but [[Delete]] returned false: ${P}`,
);
} else {
+ // The provided property was successfully deleted.
+ //
+ // Return the provided value.
return O;
}
};
@@ -235,7 +251,7 @@ export const deleteOwnProperty = (O, P) => {
* properties as nonconfigurable and (if data properties) nonwritable,
* and returns the object.
*
- * ※ This is effectively an alias for `Object.freeze`.
+ * ※ This is effectively an alias for `Object.freeze´.
*/
export const freeze = (O) => objectFreeze(O);
@@ -247,15 +263,15 @@ export const freeze = (O) => objectFreeze(O);
* property with the same value.
*
* - For accessor properties, create a nonconfigurable accessor
- * property with the same getter *and* setter.
+ * property with the same getter ⹐and⹑ setter.
*
* The prototype for the resulting object will be taken from the
- * `.prototype` property of the provided constructor, or the
- * `.prototype` of the `.constructor` of the provided object if the
+ * `.prototype´ property of the provided constructor, or the
+ * `.prototype´ of the `.constructor´ of the provided object if the
* provided constructor is undefined. If the used constructor has a
- * nonnullish `.[Symbol.species]`, that will be used instead. If the
+ * nonnullish `.[Symbol.species]´, that will be used instead. If the
* used constructor or species is nullish or does not have a
- * `.prototype` property, the prototype is set to null.
+ * `.prototype´ property, the prototype is set to null.
*
* ※ The prototype of the provided object itself is ignored.
*/
@@ -263,13 +279,13 @@ export const frozenCopy = (O, constructor = O?.constructor) => {
if (O == null) {
// O is null or undefined.
throw new TypeError(
- "Piscēs: Cannot copy properties of null or undefined.",
+ `${PISCĒS}: Cannot copy properties of null or undefined.`,
);
} else {
// O is not null or undefined.
//
// (If not provided, the constructor will be the value of getting
- // the `.constructor` property of O.)
+ // the `.constructor´ property of O.)
const species = constructor?.[SPECIES] ?? constructor;
const copy = create(
species == null || !("prototype" in species)
@@ -278,6 +294,8 @@ export const frozenCopy = (O, constructor = O?.constructor) => {
);
const keys = ownKeys(O);
for (let k = 0; k < keys.length; ++k) {
+ // Iterate over each key and define the appropriate value on the
+ // result.
const P = keys[k];
const Desc = getOwnPropertyDescriptor(O, P);
if (Desc.enumerable) {
@@ -316,15 +334,23 @@ export const frozenCopy = (O, constructor = O?.constructor) => {
* key.
*
* ☡ This function throws if the provided property key does not have an
- * associated value which is callable.
+ * associated value which is either nullish or callable.
*/
export const getMethod = (V, P) => {
const func = V[P];
if (func == null) {
- return undefined;
+ // The value of the provided property is nullish.
+ //
+ // Return undefined.
+ return UNDEFINED;
} else if (typeof func !== "function") {
- throw new TypeError(`Piscēs: Method not callable: ${P}`);
+ // The value of the provided property is not callable; this is an
+ // error.
+ throw new TypeError(`${PISCĒS}: Method not callable: ${P}`);
} else {
+ // The value of the provided property is callable.
+ //
+ // Return it.
return func;
}
};
@@ -334,12 +360,14 @@ export const getMethod = (V, P) => {
* provided property key on the provided value, or null if none exists.
*
* ※ This is effectively an alias for
- * `Object.getOwnPropertyDescriptor`, but the return value is a proxied
+ * `Object.getOwnPropertyDescriptor´, but the return value is a proxied
* object with null prototype.
*/
export const getOwnPropertyDescriptor = (O, P) => {
const desc = objectGetOwnPropertyDescriptor(O, P);
- return desc === UNDEFINED ? UNDEFINED : toPropertyDescriptor(desc);
+ return desc === UNDEFINED
+ ? UNDEFINED
+ : toPropertyDescriptorRecord(desc);
};
/**
@@ -347,7 +375,7 @@ export const getOwnPropertyDescriptor = (O, P) => {
* provided value.
*
* ※ This is effectively an alias for
- * `Object.getOwnPropertyDescriptors`, but the values on the resulting
+ * `Object.getOwnPropertyDescriptors´, but the values on the resulting
* object are proxied objects with null prototypes.
*/
export const getOwnPropertyDescriptors = (O) => {
@@ -355,6 +383,8 @@ export const getOwnPropertyDescriptors = (O) => {
const keys = ownKeys(obj);
const descriptors = {};
for (let k = 0; k < keys.length; ++k) {
+ // Iterate over the keys of the provided object and collect its
+ // descriptors.
const key = keys[k];
defineOwnDataProperty(
descriptors,
@@ -366,9 +396,31 @@ export const getOwnPropertyDescriptors = (O) => {
};
/**
- * Returns an array of property keys on the provided value.
+ * Returns an array of own property entries on the provided value,
+ * using the provided receiver if given.
+ */
+export const getOwnPropertyEntries = (O, Receiver = O) => {
+ const obj = toObject(O);
+ const keys = ownKeys(obj);
+ const target = Receiver === UNDEFINED ? obj : toObject(Receiver);
+ const result = createArray(keys.length);
+ for (let k = 0; k < keys.length; ++k) {
+ // Iterate over each key and add the corresponding entry to the
+ // result.
+ const key = keys[k];
+ defineOwnDataProperty(
+ result,
+ k,
+ [key, getOwnPropertyValue(obj, keys[k], target)],
+ );
+ }
+ return result;
+};
+
+/**
+ * Returns an array of own property keys on the provided value.
*
- * ※ This is effectively an alias for `Reflect.ownKeys`, except that
+ * ※ This is effectively an alias for `Reflect.ownKeys´, except that
* it does not require that the argument be an object.
*/
export const getOwnPropertyKeys = (O) => ownKeys(toObject(O));
@@ -379,7 +431,7 @@ export const getOwnPropertyKeys = (O) => ownKeys(toObject(O));
*
* ☡ This includes both enumerable and non·enumerable properties.
*
- * ※ This is effectively an alias for `Object.getOwnPropertyNames`.
+ * ※ This is effectively an alias for `Object.getOwnPropertyNames´.
*/
export const getOwnPropertyStrings = (O) => getOwnPropertyNames(O);
@@ -390,16 +442,68 @@ export const getOwnPropertyStrings = (O) => getOwnPropertyNames(O);
* ☡ This includes both enumerable and non·enumerable properties.
*
* ※ This is effectively an alias for
- * `Object.getOwnPropertySymbols`.
+ * `Object.getOwnPropertySymbols´.
*/
export const getOwnPropertySymbols = (O) =>
objectGetOwnPropertySymbols(O);
+/**
+ * Returns the value of the provided own property on the provided
+ * value using the provided receiver, or undefined if the provided
+ * property is not an own property on the provided value.
+ *
+ * ※ If the receiver is not provided, it defaults to the provided
+ * value.
+ */
+export const getOwnPropertyValue = (O, P, Receiver = UNDEFINED) => {
+ const obj = toObject(O);
+ const desc = getOwnPropertyDescriptor(O, P);
+ if (desc === UNDEFINED) {
+ // The provided property is not an own property on the provided
+ // value.
+ //
+ // Return undefined.
+ return UNDEFINED;
+ }
+ if (isDataDescriptor(desc)) {
+ // The provided property is a data property.
+ //
+ // Return its value.
+ return desc.value;
+ } else {
+ // The provided property is an accessor property.
+ //
+ // Get its value using the appropriate receiver.
+ const target = Receiver === UNDEFINED ? obj : toObject(Receiver);
+ return call(desc.get, target, []);
+ }
+};
+
+/**
+ * Returns an array of own property values on the provided value, using
+ * the provided receiver if given.
+ */
+export const getOwnPropertyValues = (O, Receiver = O) => {
+ const obj = toObject(O);
+ const keys = ownKeys(obj);
+ const target = Receiver === UNDEFINED ? obj : toObject(Receiver);
+ const result = createArray(keys.length);
+ for (let k = 0; k < keys.length; ++k) {
+ // Iterate over each key and collect the values.
+ defineOwnDataProperty(
+ result,
+ k,
+ getOwnPropertyValue(obj, keys[k], target),
+ );
+ }
+ return result;
+};
+
/**
* Returns the value of the provided property key on the provided
* value.
*
- * ※ This is effectively an alias for `Reflect.get`, except that it
+ * ※ This is effectively an alias for `Reflect.get´, except that it
* does not require that the argument be an object.
*/
export const getPropertyValue = (O, P, Receiver = O) =>
@@ -408,7 +512,7 @@ export const getPropertyValue = (O, P, Receiver = O) =>
/**
* Returns the prototype of the provided value.
*
- * ※ This is effectively an alias for `Object.getPrototypeOf`.
+ * ※ This is effectively an alias for `Object.getPrototypeOf´.
*/
export const getPrototype = (O) => getPrototypeOf(O);
@@ -416,7 +520,7 @@ export const getPrototype = (O) => getPrototypeOf(O);
* Returns whether the provided value has an own property with the
* provided property key.
*
- * ※ This is effectively an alias for `Object.hasOwn`.
+ * ※ This is effectively an alias for `Object.hasOwn´.
*/
export const hasOwnProperty = (O, P) => hasOwn(O, P);
@@ -424,7 +528,7 @@ export const hasOwnProperty = (O, P) => hasOwn(O, P);
* Returns whether the provided property key exists on the provided
* value.
*
- * ※ This is effectively an alias for `Reflect.has`, except that it
+ * ※ This is effectively an alias for `Reflect.has´, except that it
* does not require that the argument be an object.
*
* ※ This includes properties present on the prototype chain.
@@ -434,12 +538,18 @@ export const hasProperty = (O, P) => has(toObject(O), P);
/** Returns whether the provided value is an arraylike object. */
export const isArraylikeObject = ($) => {
if (type($) !== "object") {
+ // The provided value is not an object.
return false;
} else {
+ // The provided value is an object.
try {
- lengthOfArraylike($); // throws if not arraylike
+ // Try to get the length and return true.
+ //
+ // ※ If this throws, the object is not arraylike.
+ lengthOfArraylike($);
return true;
} catch {
+ // Getting the length failed; return false.
return false;
}
}
@@ -468,16 +578,240 @@ export const isConcatSpreadableObject = ($) => {
*
* ※ This function returns false for nonobjects.
*
- * ※ This is effectively an alias for `Object.isExtensible`.
+ * ※ This is effectively an alias for `Object.isExtensible´.
*/
export const isExtensibleObject = (O) => isExtensible(O);
+export const {
+ /**
+ * Returns whether the provided value is a property descriptor record
+ * as created by `toPropertyDescriptor´.
+ *
+ * ※ This function is provided to enable inspection of whether an
+ * object uses the ♓🧩 Piscēs property descriptor record proxy
+ * implementation, not as a general test of whether an object
+ * satisfies the requirements for property descriptors. In most
+ * cases, a more specific test, like `isAccessorDescriptor´,
+ * `isDataDescriptor´, or `isGenericDescriptor´, is preferrable.
+ */
+ isPropertyDescriptorRecord,
+
+ /**
+ * Converts the provided value to a property descriptor record.
+ *
+ * ※ The prototype of a property descriptor record is always `null´.
+ *
+ * ※ Actually constructing a property descriptor object using this
+ * class is only necessary if you need strict guarantees about the
+ * types of its properties; the resulting object is proxied to ensure
+ * the types match what one would expect from composing
+ * `FromPropertyDescriptor´ and `ToPropertyDescriptor´ in the
+ * Ecmascript specification.
+ */
+ toPropertyDescriptorRecord,
+} = (() => {
+ const proxyConstructor = Proxy;
+ const { add: weakSetAdd, has: weakSetHas } = WeakSet.prototype;
+ const propertyDescriptorRecords = new WeakSet();
+ const coercePropertyDescriptorValue = (P, V) => {
+ switch (P) {
+ case "configurable":
+ case "enumerable":
+ case "writable":
+ return !!V;
+ case "value":
+ return V;
+ case "get":
+ if (V !== UNDEFINED && typeof V !== "function") {
+ // The provided value is not callable; this is an error.
+ throw new TypeError(
+ `${PISCĒS}: Getters must be callable.`,
+ );
+ } else {
+ // The provided value is callable.
+ return V;
+ }
+ case "set":
+ if (V !== UNDEFINED && typeof V !== "function") {
+ // The provided value is not callable; this is an error.
+ throw new TypeError(
+ `${PISCĒS}: Setters must be callable.`,
+ );
+ } else {
+ // The provided value is callable.
+ return V;
+ }
+ default:
+ return V;
+ }
+ };
+ const propertyDescriptorProxyHandler = objectFreeze(
+ assign(
+ create(null),
+ {
+ defineProperty(O, P, Desc) {
+ if (
+ P === "configurable" || P === "enumerable"
+ || P === "writable" || P === "value"
+ || P === "get" || P === "set"
+ ) {
+ // `P´ is a property descriptor attribute.
+ const desc = assign(objectCreate(null), Desc);
+ if ("get" in desc || "set" in desc) {
+ // `Desc´ is an accessor property descriptor.
+ throw new TypeError(
+ `${PISCĒS}: Property descriptor attributes must be data properties.`,
+ );
+ } else if ("value" in desc || !(P in O)) {
+ // `Desc´ has a value or `P´ does not already exist on
+ // `O´.
+ desc.value = coercePropertyDescriptorValue(
+ P,
+ desc.value,
+ );
+ } else {
+ // `Desc´ is not an accessor property descriptor and has
+ // no value, but an existing value is present on `O´.
+ /* do nothing */
+ }
+ const isAccessorDescriptor = "get" === P || "set" === P
+ || "get" in O || "set" in O;
+ const isDataDescriptor = "value" === P
+ || "writable" === P
+ || "value" in O || "writable" in O;
+ if (isAccessorDescriptor && isDataDescriptor) {
+ // Both accessor and data attributes will be present on
+ // `O´ after defining `P´; this is an error.
+ throw new TypeError(
+ `${PISCĒS}: Property descriptors cannot specify both accessor and data attributes.`,
+ );
+ } else {
+ // `P´ can be safely defined on `O´.
+ return reflectDefineProperty(O, P, desc);
+ }
+ } else {
+ // `P´ is not a property descriptor attribute.
+ return reflectDefineProperty(O, P, Desc);
+ }
+ },
+ setPrototypeOf(O, V) {
+ if (V !== null) {
+ // `V´ is not the property descriptor prototype.
+ return false;
+ } else {
+ // `V´ is the property descriptor prototype.
+ return reflectSetPrototypeOf(O, V);
+ }
+ },
+ },
+ ),
+ );
+
+ return {
+ isPropertyDescriptorRecord: ($) =>
+ call(weakSetHas, propertyDescriptorRecords, [$]),
+ toPropertyDescriptorRecord: (Obj) => {
+ if (type(Obj) !== "object") {
+ // The provided value is not an object; this is an error.
+ throw new TypeError(
+ `${PISCĒS}: Cannot convert primitive to property descriptor: ${O}.`,
+ );
+ } else {
+ // The provided value is an object.
+ const desc = create(null);
+ if ("enumerable" in Obj) {
+ // An enumerable property is specified.
+ defineOwnDataProperty(desc, "enumerable", !!Obj.enumerable);
+ } else {
+ // An enumerable property is not specified.
+ /* do nothing */
+ }
+ if ("configurable" in Obj) {
+ // A configurable property is specified.
+ defineOwnDataProperty(
+ desc,
+ "configurable",
+ !!Obj.configurable,
+ );
+ } else {
+ // A configurable property is not specified.
+ /* do nothing */
+ }
+ if ("value" in Obj) {
+ // A value property is specified.
+ defineOwnDataProperty(desc, "value", Obj.value);
+ } else {
+ // A value property is not specified.
+ /* do nothing */
+ }
+ if ("writable" in Obj) {
+ // A writable property is specified.
+ defineOwnDataProperty(desc, "writable", !!Obj.writable);
+ } else {
+ // A writable property is not specified.
+ /* do nothing */
+ }
+ if ("get" in Obj) {
+ // A get property is specified.
+ const getter = Obj.get;
+ if (getter !== UNDEFINED && typeof getter !== "function") {
+ // The getter is not callable; this is an error.
+ throw new TypeError(
+ `${PISCĒS}: Getters must be callable.`,
+ );
+ } else {
+ // The getter is callable.
+ defineOwnDataProperty(desc, "get", Obj.get);
+ }
+ } else {
+ // A get property is not specified.
+ /* do nothing */
+ }
+ if ("set" in Obj) {
+ // A set property is specified.
+ const setter = Obj.set;
+ if (setter !== UNDEFINED && typeof setter !== "function") {
+ // The setter is not callable; this is an error.
+ throw new TypeError(
+ `${PISCĒS}: Setters must be callable.`,
+ );
+ } else {
+ // The setter is callable.
+ defineOwnDataProperty(desc, "set", Obj.set);
+ }
+ } else {
+ // A set property is not specified.
+ /* do nothing */
+ }
+ if (
+ ("get" in desc || "set" in desc)
+ && ("value" in desc || "writable" in desc)
+ ) {
+ // Both accessor and data attributes have been defined; this
+ // is an error.
+ throw new TypeError(
+ `${PISCĒS}: Property descriptors cannot specify both accessor and data attributes.`,
+ );
+ } else {
+ // The property descriptor is valid.
+ const record = new proxyConstructor(
+ desc,
+ propertyDescriptorProxyHandler,
+ );
+ call(weakSetAdd, propertyDescriptorRecords, [record]);
+ return record;
+ }
+ }
+ },
+ };
+})();
+
/**
* Returns whether the provided value is an unfrozen object.
*
* ※ This function returns false for nonobjects.
*
- * ※ This is effectively an alias for `!Object.isFrozen`.
+ * ※ This is effectively an alias for `!Object.isFrozen´.
*/
export const isUnfrozenObject = (O) => !isFrozen(O);
@@ -486,7 +820,7 @@ export const isUnfrozenObject = (O) => !isFrozen(O);
*
* ※ This function returns false for nonobjects.
*
- * ※ This is effectively an alias for `!Object.isSealed`.
+ * ※ This is effectively an alias for `!Object.isSealed´.
*/
export const isUnsealedObject = (O) => !isSealed(O);
@@ -504,7 +838,7 @@ export const lengthOfArraylike = ({ length }) => toLength(length);
* Returns an array of key~value pairs for the enumerable,
* string‐valued property keys on the provided value.
*
- * ※ This is effectively an alias for `Object.entries`.
+ * ※ This is effectively an alias for `Object.entries´.
*/
export const namedEntries = (O) => entries(O);
@@ -512,7 +846,7 @@ export const namedEntries = (O) => entries(O);
* Returns an array of the enumerable, string‐valued property keys on
* the provided value.
*
- * ※ This is effectively an alias for `Object.keys`.
+ * ※ This is effectively an alias for `Object.keys´.
*/
export const namedKeys = (O) => keys(O);
@@ -520,7 +854,7 @@ export const namedKeys = (O) => keys(O);
* Returns an array of property values for the enumerable,
* string‐valued property keys on the provided value.
*
- * ※ This is effectively an alias for `Object.values`.
+ * ※ This is effectively an alias for `Object.values´.
*/
export const namedValues = (O) => values(O);
@@ -528,7 +862,7 @@ export const namedValues = (O) => values(O);
* Returns a new object with the provided prototype and property
* descriptors.
*
- * ※ This is effectively an alias for `Object.create`.
+ * ※ This is effectively an alias for `Object.create´.
*/
export const objectCreate = (O, Properties) => create(O, Properties);
@@ -536,7 +870,7 @@ export const objectCreate = (O, Properties) => create(O, Properties);
* Returns a new object with property keys and values from the provided
* iterable value.
*
- * ※ This is effectively an alias for `Object.fromEntries`.
+ * ※ This is effectively an alias for `Object.fromEntries´.
*/
export const objectFromEntries = (iterable) => fromEntries(iterable);
@@ -544,7 +878,7 @@ export const objectFromEntries = (iterable) => fromEntries(iterable);
* Marks the provided object as non·extensible, and returns the
* object.
*
- * ※ This is effectively an alias for `Object.preventExtensions`.
+ * ※ This is effectively an alias for `Object.preventExtensions´.
*/
export const preventExtensions = (O) => objectPreventExtensions(O);
@@ -552,7 +886,7 @@ export const preventExtensions = (O) => objectPreventExtensions(O);
* Marks the provided object as non·extensible and marks all its
* properties as nonconfigurable, and returns the object.
*
- * ※ This is effectively an alias for `Object.seal`.
+ * ※ This is effectively an alias for `Object.seal´.
*/
export const seal = (O) => objectSeal(O);
@@ -560,21 +894,26 @@ export const seal = (O) => objectSeal(O);
* Sets the provided property key to the provided value on the provided
* object and returns the object.
*
- * ※ This function differs from `Reflect.set` in that it throws if the
+ * ※ This function differs from `Reflect.set´ in that it throws if the
* setting is unsuccessful.
*
* ☡ This function throws if the first argument is not an object.
*/
export const setPropertyValue = (O, P, V, Receiver = O) => {
if (type(O) !== "object") {
+ // The provided value is not an object; this is an error.
throw new TypeError(
- `Piscēs: Tried to set property but provided value was not an object: ${V}`,
+ `${PISCĒS}: Tried to set property but provided value was not an object: ${V}`,
);
} else if (!set(O, P, V, Receiver)) {
+ // Setting the property fails; this is an error.
throw new TypeError(
- `Piscēs: Tried to set property on object but [[Set]] returned false: ${P}`,
+ `${PISCĒS}: Tried to set property on object but [[Set]] returned false: ${P}`,
);
} else {
+ // The property was successfully set.
+ //
+ // Return the provided object.
return O;
}
};
@@ -583,7 +922,7 @@ export const setPropertyValue = (O, P, V, Receiver = O) => {
* Sets the values of the enumerable own properties of the provided
* additional objects on the provided values.
*
- * ※ This is effectively an alias for `Object.assign`.
+ * ※ This is effectively an alias for `Object.assign´.
*/
export const setPropertyValues = (target, source, ...sources) => {
const to = toObject(target);
@@ -592,7 +931,9 @@ export const setPropertyValues = (target, source, ...sources) => {
// values.
const nextSource = i === -1 ? source : sources[i];
if (nextSource != null) {
- // The current source is not nullish; handle its own properties.
+ // The current source is not nullish.
+ //
+ // Handle its own properties.
const from = toObject(nextSource);
const keys = ownKeys(from);
for (let k = 0; k < keys.length; ++k) {
@@ -601,8 +942,9 @@ export const setPropertyValues = (target, source, ...sources) => {
const nextKey = keys[k];
const desc = reflectGetOwnPropertyDescriptor(from, nextKey);
if (desc !== UNDEFINED && desc.enumerable) {
- // The current key is present and enumerable; set it to its
- // corresponding value.
+ // The current key is present and enumerable.
+ //
+ // Set it to its corresponding value.
const propValue = from[nextKey];
to[nextKey] = propValue;
} else {
@@ -622,21 +964,24 @@ export const setPropertyValues = (target, source, ...sources) => {
* Sets the prototype of the provided object to the provided value and
* returns the object.
*
- * ※ This is effectively an alias for `Object.setPrototypeOf`, but it
- * won’t throw when setting the prototype of a primitive to its current
+ * ※ This is effectively an alias for `Object.setPrototypeOf´, but it
+ * won¦t throw when setting the prototype of a primitive to its current
* value.
*/
export const setPrototype = (O, proto) => {
const obj = toObject(O);
if (O === obj) {
- // The provided value is an object; set its prototype normally.
+ // The provided value is an object.
+ //
+ // Set its prototype normally.
return setPrototypeOf(O, proto);
} else {
- // The provided value is not an object; attempt to set the
- // prototype on a coerced version with extensions prevented, then
- // return the provided value.
+ // The provided value is not an object.
+ //
+ // Attempt to set the prototype on a coerced version with
+ // extensions prevented, then return the provided value.
//
- // This will throw if the given prototype does not match the
+ // ☡ This will throw if the given prototype does not match the
// existing one on the coerced object.
setPrototypeOf(objectPreventExtensions(obj), proto);
return O;
@@ -654,19 +999,12 @@ export const toObject = ($) => {
if ($ == null) {
// The provided value is nullish; this is an error.
throw new TypeError(
- `Piscēs: Cannot convert ${$} into an object.`,
+ `${PISCĒS}: Cannot convert ${$} into an object.`,
);
} else {
- // The provided value is not nullish; coerce it to an object.
+ // The provided value is not nullish.
+ //
+ // Coerce it to an object.
return object($);
}
};
-
-/**
- * Returns the property key (symbol or string) corresponding to the
- * provided value.
- */
-export const toPropertyKey = ($) => {
- const key = toPrimitive($, "string");
- return typeof key === "symbol" ? key : `${key}`;
-};