X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/3c074e801e651cfea23eb9a1c0a8aa373c46bed0..refs/heads/current:/value.js?ds=inline diff --git a/value.js b/value.js index 4e46f63..cf858ad 100644 --- a/value.js +++ b/value.js @@ -45,21 +45,220 @@ export const { unscopables: UNSCOPABLES, } = Symbol; +export const { + /** + * ln(10). + * + * ※ This is an alias for `Math.LN10`. + */ + LN10, + + /** + * ln(2). + * + * ※ This is an alias for `Math.LN2`. + */ + LN2, + + /** + * log10(ℇ). + * + * ※ This is an alias for `Math.LOG10E`. + */ + LOG10E: LOG10ℇ, + + /** + * log2(ℇ). + * + * ※ This is an alias for `Math.LOG2E`. + */ + LOG2E: LOG2ℇ, + + /** + * sqrt(½). + * + * ※ This is an alias for `Math.SQRT1_2`. + */ + SQRT1_2: RECIPROCAL_SQRT2, + + /** + * sqrt(2). + * + * ※ This is an alias for `Math.SQRT2`. + */ + SQRT2, + + /** + * The mathematical constant π. + * + * ※ This is an alias for `Math.PI`. + */ + PI: Π, + + /** + * The Euler number. + * + * ※ This is an alias for `Math.E`. + */ + E: ℇ, +} = Math; + +export const { + /** + * The largest number value less than infinity. + * + * ※ This is an alias for `Number.MAX_VALUE`. + */ + MAX_VALUE: MAXIMUM_NUMBER, + + /** + * 2**53 - 1. + * + * ※ 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`. + */ + MIN_VALUE: MINIMUM_NUMBER, + + /** + * -(2**53 - 1). + * + * ※ 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`. + */ + NEGATIVE_INFINITY, + + /** + * Nan. + * + * ※ This is an alias for `Number.NaN`. + */ + NaN: NAN, + + /** + * 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`. + */ + EPSILON: Ε, +} = Number; + +/** Negative zero. */ +export const NEGATIVE_ZERO = -0; + /** The null primitive. */ export const NULL = null; +/** Positive zero. */ +export const POSITIVE_ZERO = 0; + /** The undefined primitive. */ export const UNDEFINED = undefined; /** - * Returns the length of the provided arraylike value. + * Completes the provided property descriptor by setting missing values + * to their defaults. * - * This can produce larger lengths than can actually be stored in - * arrays, because no such restrictions exist on arraylike methods. - * - * ☡ This function throws if the provided value is not arraylike. + * ※ This method modifies the provided object and returns undefined. */ -export const lengthOfArraylike = ({ length }) => toLength(length); +export const completePropertyDescriptor = (Desc) => { + if (Desc === UNDEFINED) { + 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 { /** @@ -74,6 +273,12 @@ export const { */ ordinaryToPrimitive, + /** + * Returns a string function name generated from the provided value + * and optional prefix. + */ + toFunctionName, + /** * Returns the provided value converted to a primitive, or throws if * no such conversion is possible. @@ -87,6 +292,10 @@ export const { toPrimitive, } = (() => { const { apply: call } = Reflect; + const getSymbolDescription = Object.getOwnPropertyDescriptor( + Symbol.prototype, + "description", + ).get; return { ordinaryToPrimitive: (O, hint) => { @@ -114,6 +323,21 @@ export const { "Piscēs: Unable to convert object to primitive", ); }, + toFunctionName: ($, prefix = UNDEFINED) => { + const key = toPrimitive($, "string"); + const name = (() => { + if (typeof key === "symbol") { + // The provided value is a symbol; format its description. + const description = call(getSymbolDescription, key, []); + return description === UNDEFINED ? "" : `[${description}]`; + } else { + // The provided value not a symbol; convert it to a string + // property key. + return `${key}`; + } + })(); + return prefix !== UNDEFINED ? `${prefix} ${name}` : name; + }, toPrimitive: ($, preferredType = "default") => { const hint = `${preferredType}`; if ( @@ -126,8 +350,8 @@ export const { ); } 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") { @@ -179,10 +403,7 @@ export const { toLength, } = (() => { const { floor, max, min } = Math; - const { - MAX_SAFE_INTEGER: MAXIMUM_SAFE_INTEGRAL_NUMBER, - isNaN: isNan, - } = Number; + const { isNaN: isNan } = Number; const { is } = Object; return { sameValue: (a, b) => is(a, b), @@ -227,6 +448,15 @@ 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.