]> Lady’s Gitweb - Pisces/blobdiff - value.js
Add methods for own entries and values to object.js
[Pisces] / value.js
index 1039a3ca9617d7a76b8493360eaf9a5e8456baea..cf858ad2a32bfc1b5e7445aebc67e4ee8a0f1577 100644 (file)
--- a/value.js
+++ b/value.js
@@ -260,256 +260,6 @@ export const isGenericDescriptor = (Desc) =>
   !("get" in Desc || "set" in Desc || "value" in Desc ||
     "writable" in Desc);
 
-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 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.
-   */
-  toPropertyDescriptor,
-} = (() => {
-  const {
-    assign: setPropertyValues,
-    create: objectCreate,
-    defineProperty: defineOwnProperty,
-  } = Object;
-  const {
-    apply: call,
-    defineProperty: reflectDefineProperty,
-    setPrototypeOf: reflectSetPrototypeOf,
-  } = Reflect;
-  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") {
-          throw new TypeError(
-            "Piscēs: Getters must be callable.",
-          );
-        } else {
-          return V;
-        }
-      case "set":
-        if (V !== undefined && typeof V !== "function") {
-          throw new TypeError(
-            "Piscēs: Setters must be callable.",
-          );
-        } else {
-          return V;
-        }
-      default:
-        return V;
-    }
-  };
-  const propertyDescriptorProxyHandler = Object.freeze(
-    Object.assign(
-      Object.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 = setPropertyValues(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.
-              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, [$]),
-    toPropertyDescriptor: (Obj) => {
-      if (type(Obj) !== "object") {
-        // The provided value is not an object.
-        throw new TypeError(
-          `Piscēs: Cannot convert primitive to property descriptor: ${O}.`,
-        );
-      } else {
-        // The provided value is an object.
-        const desc = objectCreate(null);
-        if ("enumerable" in Obj) {
-          // An enumerable property is specified.
-          defineOwnProperty(desc, "enumerable", {
-            configurable: true,
-            enumerable: true,
-            value: !!Obj.enumerable,
-            writable: true,
-          });
-        } else {
-          // An enumerable property is not specified.
-          /* do nothing */
-        }
-        if ("configurable" in Obj) {
-          // A configurable property is specified.
-          defineOwnProperty(desc, "configurable", {
-            configurable: true,
-            enumerable: true,
-            value: !!Obj.configurable,
-            writable: true,
-          });
-        } else {
-          // A configurable property is not specified.
-          /* do nothing */
-        }
-        if ("value" in Obj) {
-          // A value property is specified.
-          defineOwnProperty(desc, "value", {
-            configurable: true,
-            enumerable: true,
-            value: Obj.value,
-            writable: true,
-          });
-        } else {
-          // A value property is not specified.
-          /* do nothing */
-        }
-        if ("writable" in Obj) {
-          // A writable property is specified.
-          defineOwnProperty(desc, "writable", {
-            configurable: true,
-            enumerable: true,
-            value: !!Obj.writable,
-            writable: true,
-          });
-        } 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.
-            throw new TypeError("Piscēs: Getters must be callable.");
-          } else {
-            // The getter is callable.
-            defineOwnProperty(desc, "get", {
-              configurable: true,
-              enumerable: true,
-              value: getter,
-              writable: true,
-            });
-          }
-        } 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.
-            throw new TypeError("Piscēs: Setters must be callable.");
-          } else {
-            // The setter is callable.
-            defineOwnProperty(desc, "set", {
-              configurable: true,
-              enumerable: true,
-              value: setter,
-              writable: true,
-            });
-          }
-        } 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.
-          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;
-        }
-      }
-    },
-  };
-})();
-
 export const {
   /**
    * Returns the primitive value of the provided object per its
@@ -573,20 +323,20 @@ export const {
         "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.
           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.
           return `${key}`;
         }
       })();
-      return prefix !== undefined ? `${prefix} ${name}` : name;
+      return prefix !== UNDEFINED ? `${prefix} ${name}` : name;
     },
     toPrimitive: ($, preferredType = "default") => {
       const hint = `${preferredType}`;
@@ -600,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") {
@@ -698,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.
This page took 0.026772 seconds and 4 git commands to generate.