X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/37c295ffa9d5a062fe15d78427e2a7096a416bb3..9c6be9646631101a3883d4dac08495d5e35e9977:/value.js?ds=sidebyside
diff --git a/value.js b/value.js
index 6471ea3..6956b6f 100644
--- a/value.js
+++ b/value.js
@@ -1,47 +1,52 @@
-// ♓🌟 Piscēs ∷ value.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 ∷ value.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 .
+ */
+
+const PISCĒS = "♓🧩 Piscēs";
export const {
- /** The welknown `@@asyncIterator` symbol. */
+ /** The welknown `@@asyncIterator´ symbol. */
asyncIterator: ASYNC_ITERATOR,
- /** The welknown `@@hasInstance` symbol. */
+ /** The welknown `@@hasInstance´ symbol. */
hasInstance: HAS_INSTANCE,
- /** The welknown `@@isConcatSpreadable` symbol. */
+ /** The welknown `@@isConcatSpreadable´ symbol. */
isConcatSpreadable: IS_CONCAT_SPREADABLE,
- /** The welknown `@@iterator` symbol. */
+ /** The welknown `@@iterator´ symbol. */
iterator: ITERATOR,
- /** The welknown `@@match` symbol. */
+ /** The welknown `@@match´ symbol. */
match: MATCH,
- /** The welknown `@@matchAll` symbol. */
+ /** The welknown `@@matchAll´ symbol. */
matchAll: MATCH_ALL,
- /** The welknown `@@replace` symbol. */
+ /** The welknown `@@replace´ symbol. */
replace: REPLACE,
- /** The welknown `@@species` symbol. */
+ /** The welknown `@@species´ symbol. */
species: SPECIES,
- /** The welknown `@@split` symbol. */
+ /** The welknown `@@split´ symbol. */
split: SPLIT,
- /** The welknown `@@toPrimitive` symbol. */
+ /** The welknown `@@toPrimitive´ symbol. */
toPrimitive: TO_PRIMITIVE,
- /** The welknown `@@toStringTag` symbol. */
+ /** The welknown `@@toStringTag´ symbol. */
toStringTag: TO_STRING_TAG,
- /** The welknown `@@unscopables` symbol. */
+ /** The welknown `@@unscopables´ symbol. */
unscopables: UNSCOPABLES,
} = Symbol;
@@ -49,116 +54,116 @@ export const {
/**
* ln(10).
*
- * ※ This is an alias for `Math.LN10`.
+ * ※ This is an alias for `Math.LN10´.
*/
- LN10,
+ LN10: LN_10,
/**
* ln(2).
*
- * ※ This is an alias for `Math.LN2`.
+ * ※ This is an alias for `Math.LN2´.
*/
- LN2,
+ LN2: LN_2,
/**
- * log10(ℇ).
+ * log10(e).
*
- * ※ This is an alias for `Math.LOG10E`.
+ * ※ This is an alias for `Math.LOG10E´.
*/
- LOG10E: LOG10ℇ,
+ LOG10E: LOG10_𝑒,
/**
- * log2(ℇ).
+ * log2(e).
*
- * ※ This is an alias for `Math.LOG2E`.
+ * ※ This is an alias for `Math.LOG2E´.
*/
- LOG2E: LOG2ℇ,
+ LOG2E: LOG2_𝑒,
/**
* sqrt(½).
*
- * ※ This is an alias for `Math.SQRT1_2`.
+ * ※ This is an alias for `Math.SQRT1_2´.
*/
- SQRT1_2: RECIPROCAL_SQRT2,
+ SQRT1_2: RECIPROCAL_SQRT_2,
/**
* sqrt(2).
*
- * ※ This is an alias for `Math.SQRT2`.
+ * ※ This is an alias for `Math.SQRT2´.
*/
- SQRT2,
+ SQRT2: SQRT_2,
/**
- * The mathematical constant π.
+ * The mathematical constant 𝑒.
*
- * ※ This is an alias for `Math.PI`.
+ * ※ This is an alias for `Math.E´.
*/
- PI: Π,
+ E: 𝑒,
/**
- * The Euler number.
+ * The mathematical constant 𝜋.
*
- * ※ This is an alias for `Math.E`.
+ * ※ This is an alias for `Math.PI´.
*/
- E: ℇ,
+ PI: 𝜋,
} = Math;
export const {
/**
* The largest number value less than infinity.
*
- * ※ This is an alias for `Number.MAX_VALUE`.
+ * ※ This is an alias for `Number.MAX_VALUE´.
*/
MAX_VALUE: MAXIMUM_NUMBER,
/**
- * 2**53 - 1.
+ * 2^53 - 1.
*
- * ※ This is an alias for `Number.MAX_SAFE_INTEGER`.
+ * ※ This is an alias for `Number.MAX_SAFE_INTEGER´.
*/
MAX_SAFE_INTEGER: MAXIMUM_SAFE_INTEGRAL_NUMBER,
/**
* The smallest number value greater than negative infinity.
*
- * ※ This is an alias for `Number.MIN_VALUE`.
+ * ※ This is an alias for `Number.MIN_VALUE´.
*/
MIN_VALUE: MINIMUM_NUMBER,
/**
- * -(2**53 - 1).
+ * -(2^53 - 1).
*
- * ※ This is an alias for `Number.MIN_SAFE_INTEGER`.
+ * ※ This is an alias for `Number.MIN_SAFE_INTEGER´.
*/
MIN_SAFE_INTEGER: MINIMUM_SAFE_INTEGRAL_NUMBER,
/**
* Negative infinity.
*
- * ※ This is an alias for `Number.NEGATIVE_INFINITY`.
+ * ※ This is an alias for `Number.NEGATIVE_INFINITY´.
*/
NEGATIVE_INFINITY,
/**
* Nan.
*
- * ※ This is an alias for `Number.NaN`.
+ * ※ This is an alias for `Number.NaN´.
*/
NaN: NAN,
/**
* Positive infinity.
*
- * ※ This is an alias for `Number.POSITIVE_INFINITY`.
+ * ※ This is an alias for `Number.POSITIVE_INFINITY´.
*/
POSITIVE_INFINITY,
/**
* The difference between 1 and the smallest number greater than 1.
*
- * ※ This is an alias for `Number.EPSILON`.
+ * ※ This is an alias for `Number.EPSILON´.
*/
- EPSILON: Ε,
+ EPSILON: 𝜀,
} = Number;
/** Negative zero. */
@@ -173,13 +178,101 @@ export const POSITIVE_ZERO = 0;
/** The undefined primitive. */
export const UNDEFINED = undefined;
+/**
+ * Completes the provided property descriptor by setting missing values
+ * to their defaults.
+ *
+ * ※ This method modifies the provided object and returns undefined.
+ */
+export const completePropertyDescriptor = (Desc) => {
+ if (Desc === UNDEFINED) {
+ // A description was not provided; this is an error.
+ throw new TypeError(
+ `${PISCĒS}: Cannot complete undefined property descriptor.`,
+ );
+ } else if (!("get" in Desc || "set" in Desc)) {
+ // This is a generic or data descriptor.
+ if (!("value" in Desc)) {
+ // `value´ is not defined on this.
+ Desc.value = UNDEFINED;
+ } else {
+ // `value´ is already defined on this.
+ /* do nothing */
+ }
+ if (!("writable" in Desc)) {
+ // `writable´ is not defined on this.
+ Desc.writable = false;
+ } else {
+ // `writable´ is already defined on this.
+ /* do nothing */
+ }
+ } else {
+ // This is not a generic or data descriptor.
+ if (!("get" in Desc)) {
+ // `get´ is not defined on this.
+ Desc.get = UNDEFINED;
+ } else {
+ // `get´ is already defined on this.
+ /* do nothing */
+ }
+ if (!("set" in Desc)) {
+ // `set´ is not defined on this.
+ Desc.set = UNDEFINED;
+ } else {
+ // `set´ is already defined on this.
+ /* do nothing */
+ }
+ }
+ if (!("enumerable" in Desc)) {
+ // `enumerable´ is not defined on this.
+ Desc.enumerable = false;
+ } else {
+ // `enumerable´ is already defined on this.
+ /* do nothing */
+ }
+ if (!("configurable" in Desc)) {
+ // `configurable´ is not defined on this.
+ Desc.configurable = false;
+ } else {
+ // `configurable´ is already defined on this.
+ /* do nothing */
+ }
+};
+
+/** Gets whether the provided value is an accessor descrtiptor. */
+export const isAccessorDescriptor = (Desc) =>
+ Desc !== UNDEFINED && ("get" in Desc || "set" in Desc);
+
+/** Gets whether the provided value is a data descrtiptor. */
+export const isDataDescriptor = (Desc) =>
+ Desc !== UNDEFINED && ("value" in Desc || "writable" in Desc);
+
+/**
+ * Gets whether the provided value is a fully‐populated property
+ * descriptor.
+ */
+export const isFullyPopulatedDescriptor = (Desc) =>
+ Desc !== UNDEFINED
+ && ("value" in Desc && "writable" in Desc
+ || "get" in Desc && "set" in Desc)
+ && "enumerable" in Desc && "configurable" in Desc;
+
+/**
+ * Gets whether the provided value is a generic (not accessor or data)
+ * descrtiptor.
+ */
+export const isGenericDescriptor = (Desc) =>
+ Desc !== UNDEFINED
+ && !("get" in Desc || "set" in Desc || "value" in Desc
+ || "writable" in Desc);
+
export const {
/**
* Returns the primitive value of the provided object per its
- * `.toString` and `.valueOf` methods.
+ * `.toString´ and `.valueOf´ methods.
*
- * If the provided hint is "string", then `.toString` takes
- * precedence; otherwise, `.valueOf` does.
+ * If the provided hint is "string", then `.toString´ takes
+ * precedence; otherwise, `.valueOf´ does.
*
* Throws an error if both of these methods are not callable or do
* not return a primitive.
@@ -198,7 +291,7 @@ export const {
*
* The provided preferred type, if specified, should be "string",
* "number", or "default". If the provided input has a
- * `.[Symbol.toPrimitive]` method, this function will throw rather
+ * `.[Symbol.toPrimitive]´ method, this function will throw rather
* than calling that method with a preferred type other than one of
* the above.
*/
@@ -216,6 +309,11 @@ export const {
? ["toString", "valueOf"]
: ["valueOf", "toString"];
for (let index = 0; index < methodNames.length; ++index) {
+ // Test the methods in the order determined above (based on the
+ // hint) and return the result if the method returns a
+ // primitive.
+ //
+ // ☡ If this loop exits with·out returning, it is an error.
const method = O[methodNames[index]];
if (typeof method === "function") {
// Method is callable.
@@ -233,44 +331,47 @@ export const {
}
}
throw new TypeError(
- "Piscēs: Unable to convert object to primitive",
+ `${PISCĒS}: Unable to convert object to primitive.`,
);
},
- toFunctionName: ($, prefix = undefined) => {
+ toFunctionName: ($, prefix = UNDEFINED) => {
const key = toPrimitive($, "string");
const name = (() => {
if (typeof key === "symbol") {
- // The provided value is a symbol; format its description.
+ // The provided value is a symbol.
+ //
+ // Format its description.
const description = call(getSymbolDescription, key, []);
- return description === undefined ? "" : `[${description}]`;
+ return description === UNDEFINED ? "" : `[${description}]`;
} else {
- // The provided value not a symbol; convert it to a string
- // property key.
+ // The provided value not a symbol.
+ //
+ // Convert it to a string property key.
return `${key}`;
}
})();
- return prefix !== undefined ? `${prefix} ${name}` : name;
+ return prefix !== UNDEFINED ? `${prefix} ${name}` : name;
},
toPrimitive: ($, preferredType = "default") => {
const hint = `${preferredType}`;
if (
- "default" !== hint && "string" !== hint &&
- "number" !== hint
+ "default" !== hint && "string" !== hint
+ && "number" !== hint
) {
// An invalid preferred type was specified.
throw new TypeError(
- `Piscēs: Invalid preferred type: ${preferredType}.`,
+ `${PISCĒS}: Invalid preferred type: ${preferredType}.`,
);
} else if (type($) === "object") {
// The provided value is an object.
- const exoticToPrim = $[TO_PRIMITIVE] ?? undefined;
- if (exoticToPrim !== undefined) {
+ const exoticToPrim = $[TO_PRIMITIVE] ?? UNDEFINED;
+ if (exoticToPrim !== UNDEFINED) {
// The provided value has an exotic primitive conversion
// method.
if (typeof exoticToPrim !== "function") {
// The method is not callable.
throw new TypeError(
- "Piscēs: `.[Symbol.toPrimitive]` was neither nullish nor callable.",
+ `${PISCĒS}: .[Symbol.toPrimitive] was neither nullish nor callable.`,
);
} else {
// The method is callable.
@@ -292,7 +393,7 @@ export const {
/**
* Returns whether the provided values are the same value.
*
- * ※ This differs from `===` in the cases of nan and zero.
+ * ※ This differs from `===´ in the cases of nan and zero.
*/
sameValue,
@@ -300,7 +401,7 @@ export const {
* Returns whether the provided values are either the same value or
* both zero (either positive or negative).
*
- * ※ This differs from `===` in the case of nan.
+ * ※ This differs from `===´ in the case of nan.
*/
sameValueZero,
@@ -327,11 +428,14 @@ export const {
// The provided values are not of the same type.
return false;
} else if (type1 === "number") {
- // The provided values are numbers; check if they are nan and
- // use strict equality otherwise.
+ // The provided values are numbers.
+ //
+ // Check if they are nan and use strict equality otherwise.
return isNan($1) && isNan($2) || $1 === $2;
} else {
- // The provided values are not numbers; use strict equality.
+ // The provided values are not numbers.
+ //
+ // Use strict equality.
return $1 === $2;
}
},
@@ -339,15 +443,19 @@ export const {
const integer = floor($);
if (isNan(integer) || integer == 0) {
// The value is zero·like.
+ //
+ // Return positive zero.
return 0;
} else {
// The value is not zero·like.
const clamped = toLength(integer);
if (clamped !== integer) {
- // Clamping the value changes it.
- throw new RangeError(`Piscēs: Index out of range: ${$}.`);
+ // Clamping the value changes it; this is an error.
+ throw new RangeError(`${PISCĒS}: Index out of range: ${$}.`);
} else {
// The value is within appropriate bounds.
+ //
+ // Return it.
return integer;
}
}
@@ -361,12 +469,21 @@ export const {
};
})();
+/**
+ * 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}`;
+};
+
/**
* Returns a lowercase string identifying the type of the provided
* value.
*
- * This differs from the value of the `typeof` operator only in the
- * cases of objects and null.
+ * This differs from the value of the `typeof´ operator only in the
+ * cases of callable objects and null.
*/
export const type = ($) => {
if ($ === null) {