]> Lady’s Gitweb - Pisces/blobdiff - object.js
Add buffer getters and setters to binary.js
[Pisces] / object.js
index a34423e7a5bbd1578154690f7f8d69767fb7e776..a4037951fcd77fa746e8aabe23a974948e29ed9a 100644 (file)
--- a/object.js
+++ b/object.js
@@ -1,14 +1,14 @@
 // ♓🌟 Piscēs ∷ object.js
 // ====================================================================
 //
 // ♓🌟 Piscēs ∷ object.js
 // ====================================================================
 //
-// Copyright © 2022 Lady [@ Lady’s Computer].
+// 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 <https://mozilla.org/MPL/2.0/>.
 
 import { bind, call } from "./function.js";
 //
 // 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 <https://mozilla.org/MPL/2.0/>.
 
 import { bind, call } from "./function.js";
-import { toPrimitive, type } from "./value.js";
+import { ITERATOR, SPECIES, toPrimitive, type } from "./value.js";
 
 /**
  * An object whose properties are lazy‐loaded from the methods on the
 
 /**
  * An object whose properties are lazy‐loaded from the methods on the
@@ -28,43 +28,53 @@ import { toPrimitive, type } from "./value.js";
  * Methods will be called with the resulting object as their this
  * value.
  *
  * Methods will be called with the resulting object as their this
  * value.
  *
- * LazyLoader objects have the same prototype as the passed methods
+ * `LazyLoader` objects have the same prototype as the passed methods
  * object.
  */
 export class LazyLoader extends null {
  * object.
  */
 export class LazyLoader extends null {
-  /** Constructs a new LazyLoader object. */
+  /**
+   * Constructs a new `LazyLoader` object.
+   *
+   * ☡ This function throws if the provided value is not an object.
+   */
   constructor(loadMethods) {
   constructor(loadMethods) {
-    const result = objectCreate(getPrototype(loadMethods));
-    const methodKeys = getOwnPropertyKeys(loadMethods);
-    for (let index = 0; index < methodKeys.length; ++index) {
-      const methodKey = methodKeys[index];
-      const { configurable, enumerable, writable } =
-        getOwnPropertyDescriptor(loadMethods, methodKey);
-      defineOwnProperty(result, methodKey, {
-        configurable: true,
-        enumerable,
-        get: () => {
-          const value = call(loadMethods[methodKey], result, []);
-          defineOwnProperty(result, methodKey, {
-            configurable,
-            enumerable,
-            value,
-            writable,
-          });
-          return value;
-        },
-        set: writable
-          ? ($) =>
+    if (type(loadMethods) !== "object") {
+      throw new TypeError(
+        `Piscēs: Cannot construct LazyLoader: Provided argument is not an object: ${loadMethods}.`,
+      );
+    } else {
+      const result = objectCreate(getPrototype(loadMethods));
+      const methodKeys = getOwnPropertyKeys(loadMethods);
+      for (let index = 0; index < methodKeys.length; ++index) {
+        const methodKey = methodKeys[index];
+        const { configurable, enumerable, writable } =
+          getOwnPropertyDescriptor(loadMethods, methodKey);
+        defineOwnProperty(result, methodKey, {
+          configurable: true,
+          enumerable,
+          get: () => {
+            const value = call(loadMethods[methodKey], result, []);
             defineOwnProperty(result, methodKey, {
               configurable,
               enumerable,
             defineOwnProperty(result, methodKey, {
               configurable,
               enumerable,
-              value: $,
+              value,
               writable,
               writable,
-            })
-          : void {},
-      });
+            });
+            return value;
+          },
+          set: writable
+            ? ($) =>
+              defineOwnProperty(result, methodKey, {
+                configurable,
+                enumerable,
+                value: $,
+                writable,
+              })
+            : void {},
+        });
+      }
+      return result;
     }
     }
-    return result;
   }
 }
 
   }
 }
 
@@ -86,15 +96,14 @@ export const { PropertyDescriptor } = (() => {
      * object.
      *
      * The resulting object is proxied to enforce types (for example,
      * object.
      *
      * The resulting object is proxied to enforce types (for example,
-     * its `enumerable` property, if defined, will always be a
+     * its `.enumerable` property, if defined, will always be a
      * boolean).
      */
      * boolean).
      */
-    //deno-lint-ignore constructor-super
     constructor(O) {
       if (type(O) !== "object") {
         // The provided value is not an object.
         throw new TypeError(
     constructor(O) {
       if (type(O) !== "object") {
         // The provided value is not an object.
         throw new TypeError(
-          "Piscēs: Cannot convert primitive to property descriptor.",
+          `Piscēs: Cannot convert primitive to property descriptor: ${O}.`,
         );
       } else {
         // The provided value is an object.
         );
       } else {
         // The provided value is an object.
@@ -386,7 +395,7 @@ export const {
    * descriptors on the enumerable own properties of the provided
    * additional objects.
    *
    * descriptors on the enumerable own properties of the provided
    * additional objects.
    *
-   * ※ This differs from Object.defineProperties in that it can take
+   * ※ This differs from `Object.defineProperties` in that it can take
    * multiple source objects.
    */
   defineOwnProperties,
    * multiple source objects.
    */
   defineOwnProperties,
@@ -410,7 +419,7 @@ export const {
    * Defines an own property on the provided object on the provided
    * property key using the provided property descriptor.
    *
    * Defines an own property on the provided object on the provided
    * property key using the provided property descriptor.
    *
-   * ※ This is an alias for Object.defineProperty.
+   * ※ This is an alias for `Object.defineProperty`.
    */
   defineProperty: defineOwnProperty,
 
    */
   defineProperty: defineOwnProperty,
 
@@ -419,7 +428,7 @@ export const {
    * properties as nonconfigurable and (if data properties)
    * nonwritable, and returns the object.
    *
    * properties as nonconfigurable and (if data properties)
    * nonwritable, and returns the object.
    *
-   * ※ This is an alias for Object.freeze.
+   * ※ This is an alias for `Object.freeze`.
    */
   freeze,
 
    */
   freeze,
 
@@ -428,7 +437,7 @@ export const {
    * provided property key on the provided object, or null if none
    * exists.
    *
    * provided property key on the provided object, or null if none
    * exists.
    *
-   * ※ This is an alias for Object.getOwnPropertyDescriptor.
+   * ※ This is an alias for `Object.getOwnPropertyDescriptor`.
    */
   getOwnPropertyDescriptor,
 
    */
   getOwnPropertyDescriptor,
 
@@ -436,7 +445,7 @@ export const {
    * Returns the property descriptors for the own properties on the
    * provided object.
    *
    * Returns the property descriptors for the own properties on the
    * provided object.
    *
-   * ※ This is an alias for Object.getOwnPropertyDescriptors.
+   * ※ This is an alias for `Object.getOwnPropertyDescriptors`.
    */
   getOwnPropertyDescriptors,
 
    */
   getOwnPropertyDescriptors,
 
@@ -446,7 +455,7 @@ export const {
    *
    * ☡ This includes both enumerable and non·enumerable properties.
    *
    *
    * ☡ This includes both enumerable and non·enumerable properties.
    *
-   * ※ This is an alias for Object.getOwnPropertyNames.
+   * ※ This is an alias for `Object.getOwnPropertyNames`.
    */
   getOwnPropertyNames: getOwnPropertyStrings,
 
    */
   getOwnPropertyNames: getOwnPropertyStrings,
 
@@ -456,14 +465,14 @@ export const {
    *
    * ☡ This includes both enumerable and non·enumerable properties.
    *
    *
    * ☡ This includes both enumerable and non·enumerable properties.
    *
-   * ※ This is an alias for Object.getOwnPropertySymbols.
+   * ※ This is an alias for `Object.getOwnPropertySymbols`.
    */
   getOwnPropertySymbols,
 
   /**
    * Returns the prototype of the provided object.
    *
    */
   getOwnPropertySymbols,
 
   /**
    * Returns the prototype of the provided object.
    *
-   * ※ This is an alias for Object.getPrototypeOf.
+   * ※ This is an alias for `Object.getPrototypeOf`.
    */
   getPrototypeOf: getPrototype,
 
    */
   getPrototypeOf: getPrototype,
 
@@ -471,36 +480,36 @@ export const {
    * Returns whether the provided object has an own property with the
    * provided property key.
    *
    * Returns whether the provided object has an own property with the
    * provided property key.
    *
-   * ※ This is an alias for Object.hasOwn.
+   * ※ This is an alias for `Object.hasOwn`.
    */
   hasOwn: hasOwnProperty,
 
   /**
    * Returns whether the provided object is extensible.
    *
    */
   hasOwn: hasOwnProperty,
 
   /**
    * Returns whether the provided object is extensible.
    *
-   * ※ This is an alias for Object.isExtensible.
+   * ※ This is an alias for `Object.isExtensible`.
    */
    */
-  isExtensible,
+  isExtensible: isExtensibleObject,
 
   /**
    * Returns whether the provided object is frozen.
    *
 
   /**
    * Returns whether the provided object is frozen.
    *
-   * ※ This is an alias for Object.isFrozen.
+   * ※ This is an alias for `Object.isFrozen`.
    */
    */
-  isFrozen,
+  isFrozen: isFrozenObject,
 
   /**
    * Returns whether the provided object is sealed.
    *
 
   /**
    * Returns whether the provided object is sealed.
    *
-   * ※ This is an alias for Object.isSealed.
+   * ※ This is an alias for `Object.isSealed`.
    */
    */
-  isSealed,
+  isSealed: isSealedObject,
 
   /**
    * Returns an array of key~value pairs for the enumerable,
    * string‐valued property keys on the provided object.
    *
 
   /**
    * Returns an array of key~value pairs for the enumerable,
    * string‐valued property keys on the provided object.
    *
-   * ※ This is an alias for Object.entries.
+   * ※ This is an alias for `Object.entries`.
    */
   entries: namedEntries,
 
    */
   entries: namedEntries,
 
@@ -508,7 +517,7 @@ export const {
    * Returns an array of the enumerable, string‐valued property keys on
    * the provided object.
    *
    * Returns an array of the enumerable, string‐valued property keys on
    * the provided object.
    *
-   * ※ This is an alias for Object.keys.
+   * ※ This is an alias for `Object.keys`.
    */
   keys: namedKeys,
 
    */
   keys: namedKeys,
 
@@ -516,7 +525,7 @@ export const {
    * Returns an array of property values for the enumerable,
    * string‐valued property keys on the provided object.
    *
    * Returns an array of property values for the enumerable,
    * string‐valued property keys on the provided object.
    *
-   * ※ This is an alias for Object.values.
+   * ※ This is an alias for `Object.values`.
    */
   values: namedValues,
 
    */
   values: namedValues,
 
@@ -524,14 +533,14 @@ export const {
    * Returns a new object with the provided prototype and property
    * descriptors.
    *
    * Returns a new object with the provided prototype and property
    * descriptors.
    *
-   * ※ This is an alias for Object.create.
+   * ※ This is an alias for `Object.create`.
    */
   create: objectCreate,
 
   /**
    * Returns a new object with the provided property keys and values.
    *
    */
   create: objectCreate,
 
   /**
    * Returns a new object with the provided property keys and values.
    *
-   * ※ This is an alias for Object.fromEntries.
+   * ※ This is an alias for `Object.fromEntries`.
    */
   fromEntries: objectFromEntries,
 
    */
   fromEntries: objectFromEntries,
 
@@ -539,7 +548,7 @@ export const {
    * Marks the provided object as non·extensible, and returns the
    * object.
    *
    * Marks the provided object as non·extensible, and returns the
    * object.
    *
-   * ※ This is an alias for Object.preventExtensions.
+   * ※ This is an alias for `Object.preventExtensions`.
    */
   preventExtensions,
 
    */
   preventExtensions,
 
@@ -547,7 +556,7 @@ export const {
    * Marks the provided object as non·extensible and marks all its
    * properties as nonconfigurable, and returns the object.
    *
    * Marks the provided object as non·extensible and marks all its
    * properties as nonconfigurable, and returns the object.
    *
-   * ※ This is an alias for Object.seal.
+   * ※ This is an alias for `Object.seal`.
    */
   seal,
 
    */
   seal,
 
@@ -555,7 +564,7 @@ export const {
    * Sets the values of the enumerable own properties of the provided
    * additional objects on the provided object.
    *
    * Sets the values of the enumerable own properties of the provided
    * additional objects on the provided object.
    *
-   * ※ This is an alias for Object.assign.
+   * ※ This is an alias for `Object.assign`.
    */
   assign: setPropertyValues,
 
    */
   assign: setPropertyValues,
 
@@ -563,7 +572,7 @@ export const {
    * Sets the prototype of the provided object to the provided value
    * and returns the object.
    *
    * Sets the prototype of the provided object to the provided value
    * and returns the object.
    *
-   * ※ This is an alias for Object.setPrototypeOf.
+   * ※ This is an alias for `Object.setPrototypeOf`.
    */
   setPrototypeOf: setPrototype,
 } = Object;
    */
   setPrototypeOf: setPrototype,
 } = Object;
@@ -573,26 +582,62 @@ export const {
    * Removes the provided property key from the provided object and
    * returns the object.
    *
    * Removes the provided property key from the provided object and
    * returns the object.
    *
-   * ☡ This function differs from Reflect.deleteProperty and the
+   * ※ This function differs from `Reflect.deleteProperty` and the
    * `delete` operator in that it throws if the deletion is
    * unsuccessful.
    * `delete` operator in that it throws if the deletion is
    * unsuccessful.
+   *
+   * ☡ This function throws if the first argument is not an object.
    */
   deleteOwnProperty,
 
    */
   deleteOwnProperty,
 
+  /**
+   * Returns an array of property keys on the provided object.
+   *
+   * ※ This is effectively an alias for `Reflect.ownKeys`, except that
+   * it does not require that the argument be an object.
+   */
+  getOwnPropertyKeys,
+
+  /**
+   * Returns the value of the provided property key on the provided
+   * object.
+   *
+   * ※ This is effectively an alias for `Reflect.get`, except that it
+   * does not require that the argument be an object.
+   */
+  getPropertyValue,
+
+  /**
+   * Returns whether the provided property key exists on the provided
+   * object.
+   *
+   * ※ This is effectively an alias for `Reflect.has`, except that it
+   * does not require that the argument be an object.
+   *
+   * ※ This includes properties present on the prototype chain.
+   */
+  hasProperty,
+
   /**
    * Sets the provided property key to the provided value on the
    * provided object and returns the object.
    *
   /**
    * Sets the provided property key to the provided value on the
    * provided object and returns the object.
    *
-   * ※ This function differs from Reflect.set in that it throws if the
-   * setting is unsuccessful.
+   * ※ This function differs from `Reflect.set` in that it throws if
+   * the setting is unsuccessful.
+   *
+   * ☡ This function throws if the first argument is not an object.
    */
   setPropertyValue,
 } = (() => {
    */
   setPropertyValue,
 } = (() => {
-  const { deleteProperty, set } = Reflect;
+  const { deleteProperty, get, has, ownKeys, set } = Reflect;
 
   return {
     deleteOwnProperty: (O, P) => {
 
   return {
     deleteOwnProperty: (O, P) => {
-      if (!deleteProperty(O, P)) {
+      if (type(O) !== "object") {
+        throw new TypeError(
+          `Piscēs: Tried to set property but provided value was not an object: ${V}`,
+        );
+      } else if (!deleteProperty(O, P)) {
         throw new TypeError(
           `Piscēs: Tried to delete property from object but [[Delete]] returned false: ${P}`,
         );
         throw new TypeError(
           `Piscēs: Tried to delete property from object but [[Delete]] returned false: ${P}`,
         );
@@ -600,8 +645,16 @@ export const {
         return O;
       }
     },
         return O;
       }
     },
+    getOwnPropertyKeys: (O) => ownKeys(toObject(O)),
+    getPropertyValue: (O, P, Receiver = O) =>
+      get(toObject(O), P, Receiver),
+    hasProperty: (O, P) => has(toObject(O), P),
     setPropertyValue: (O, P, V, Receiver = O) => {
     setPropertyValue: (O, P, V, Receiver = O) => {
-      if (!set(O, P, V, Receiver)) {
+      if (type(O) !== "object") {
+        throw new TypeError(
+          `Piscēs: Tried to set property but provided value was not an object: ${V}`,
+        );
+      } else if (!set(O, P, V, Receiver)) {
         throw new TypeError(
           `Piscēs: Tried to set property on object but [[Set]] returned false: ${P}`,
         );
         throw new TypeError(
           `Piscēs: Tried to set property on object but [[Set]] returned false: ${P}`,
         );
@@ -615,7 +668,7 @@ export const {
 export const {
   /**
    * Returns a new frozen shallow copy of the enumerable own properties
 export const {
   /**
    * Returns a new frozen shallow copy of the enumerable own properties
-   * of the provided object, according to the following rules:—
+   * of the provided object, according to the following rules :—
    *
    * - For data properties, create a nonconfigurable, nonwritable
    *   property with the same value.
    *
    * - For data properties, create a nonconfigurable, nonwritable
    *   property with the same value.
@@ -624,24 +677,22 @@ export const {
    *   property with the same getter *and* setter.
    *
    * The prototype for the resulting object will be taken from the
    *   property with the same getter *and* setter.
    *
    * The prototype for the resulting object will be taken from the
-   * `prototype` property of the provided constructor, or the
-   * `prototype` of the `constructor` of the provided object if the
+   * `.prototype` property of the provided constructor, or the
+   * `.prototype` of the `.constructor` of the provided object if the
    * provided constructor is undefined. If the used constructor has a
    * provided constructor is undefined. If the used constructor has a
-   * nonnullish `Symbol.species`, that will be used instead. If the
+   * nonnullish `.[Symbol.species]`, that will be used instead. If the
    * used constructor or species is nullish or does not have a
    * used constructor or species is nullish or does not have a
-   * `prototype` property, the prototype is set to null.
+   * `.prototype` property, the prototype is set to null.
+   *
+   * ※ The prototype of the provided object itself is ignored.
    */
   frozenCopy,
 } = (() => {
    */
   frozenCopy,
 } = (() => {
-  const {
-    iterator: iteratorSymbol,
-    species: speciesSymbol,
-  } = Symbol;
   const {
     next: generatorIteratorNext,
   } = getPrototype(function* () {}.prototype);
   const propertyDescriptorEntryIterablePrototype = {
   const {
     next: generatorIteratorNext,
   } = getPrototype(function* () {}.prototype);
   const propertyDescriptorEntryIterablePrototype = {
-    [iteratorSymbol]() {
+    [ITERATOR]() {
       return {
         next: bind(generatorIteratorNext, this.generator(), []),
       };
       return {
         next: bind(generatorIteratorNext, this.generator(), []),
       };
@@ -658,8 +709,8 @@ export const {
         // O is not null or undefined.
         //
         // (If not provided, the constructor will be the value of
         // O is not null or undefined.
         //
         // (If not provided, the constructor will be the value of
-        // getting the `constructor` property of O.)
-        const species = constructor?.[speciesSymbol] ?? constructor;
+        // getting the `.constructor` property of O.)
+        const species = constructor?.[SPECIES] ?? constructor;
         return preventExtensions(
           objectCreate(
             species == null || !("prototype" in species)
         return preventExtensions(
           objectCreate(
             species == null || !("prototype" in species)
@@ -714,46 +765,44 @@ export const {
   };
 })();
 
   };
 })();
 
-export const {
-  /**
-   * Returns an array of property keys on the provided object.
-   *
-   * ※ This is an alias for Reflect.ownKeys.
-   */
-  ownKeys: getOwnPropertyKeys,
-
-  /**
-   * Returns the value of the provided property key on the provided
-   * object.
-   *
-   * ※ This is an alias for Reflect.get.
-   */
-  get: getPropertyValue,
-
-  /**
-   * Returns whether the provided property key exists on the provided
-   * object.
-   *
-   * ※ This is an alias for Reflect.has.
-   *
-   * ※ This includes properties present on the prototype chain.
-   */
-  has: hasProperty,
-} = Reflect;
+/**
+ * Returns the function on the provided value at the provided property
+ * key.
+ *
+ * ☡ This function throws if the provided property key does not have an
+ * associated value which is callable.
+ */
+export const getMethod = (V, P) => {
+  const func = getPropertyValue(V, P);
+  if (func == null) {
+    return undefined;
+  } else if (typeof func !== "function") {
+    throw new TypeError(`Piscēs: Method not callable: ${P}`);
+  } else {
+    return func;
+  }
+};
 
 /**
  * Returns the provided value converted to an object.
  *
 
 /**
  * Returns the provided value converted to an object.
  *
- * Null and undefined are converted to a new, empty object. Other
- * primitives are wrapped. Existing objects are returned with no
- * modification.
+ * Existing objects are returned with no modification.
  *
  *
- * ※ This is effectively a nonconstructible version of the Object
- * constructor.
+ * ☡ This function throws if its argument is null or undefined.
  */
 export const { toObject } = (() => {
   const makeObject = Object;
  */
 export const { toObject } = (() => {
   const makeObject = Object;
-  return { toObject: ($) => makeObject($) };
+  return {
+    toObject: ($) => {
+      if ($ == null) {
+        throw new TypeError(
+          `Piscēs: Cannot convert ${$} into an object.`,
+        );
+      } else {
+        return makeObject($);
+      }
+    },
+  };
 })();
 
 /**
 })();
 
 /**
This page took 0.036584 seconds and 4 git commands to generate.