/** 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) {
+ 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
*/
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.
toPrimitive,
} = (() => {
const { apply: call } = Reflect;
+ const getSymbolDescription = Object.getOwnPropertyDescriptor(
+ Symbol.prototype,
+ "description",
+ ).get;
return {
ordinaryToPrimitive: (O, hint) => {
"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 (
);
} 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") {
};
})();
+/**
+ * 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.