+/**
+ * Returns −0 if the provided argument is `"-0"´; returns a number
+ * representing the index if the provided argument is a canonical
+ * numeric index string; otherwise, returns undefined.
+ *
+ * There is no clamping of the numeric index, but note that numbers
+ * above 2^53 − 1 are not safe nor valid integer indices.
+ */
+export const canonicalNumericIndexString = ($) => {
+ if (typeof $ !== "string") {
+ return UNDEFINED;
+ } else if ($ === "-0") {
+ return -0;
+ } else {
+ const n = +$;
+ return $ === `${n}` ? n : 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);
+
+/** Returns whether the provided value is an array index. */
+export const isArrayIndexString = ($) => {
+ const value = canonicalNumericIndexString($);
+ if (value !== UNDEFINED) {
+ // The provided value is a canonical numeric index string.
+ //
+ // Return whether it is in range for array indices.
+ return sameValue(value, 0)
+ || value === toLength(value) && value > 0 && value < -1 >>> 0;
+ } else {
+ // The provided value is not a canonical numeric index string.
+ return false;
+ }
+};
+
+/** 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);
+
+/** Returns whether the provided value is an integer index string. */
+export const isIntegerIndexString = ($) => {
+ const value = canonicalNumericIndexString($);
+ if (value !== UNDEFINED) {
+ // The provided value is a canonical numeric index string.
+ //
+ // Return whether it is in range for integer indices.
+ return sameValue(value, 0)
+ || value === toLength(value) && value > 0;
+ } else {
+ // The provided value is not a canonical numeric index string.
+ return false;
+ }
+};
+