]> Lady’s Gitweb - Pisces/commitdiff
Basic functions for object & function manipulation
authorLady <redacted>
Sat, 9 Jul 2022 23:02:22 +0000 (16:02 -0700)
committerLady <redacted>
Fri, 12 May 2023 03:56:47 +0000 (20:56 -0700)
base64.js
collection.js
function.js [new file with mode: 0644]
iri.js
mod.js
object.js

index 707e8e6cf819a5484975bf9902a174bee19e1d07..ff58328a0846705d6c86a0ee08d97d4b1d5c2bb2 100644 (file)
--- a/base64.js
+++ b/base64.js
@@ -7,6 +7,8 @@
 // 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 { getPrototype, hasOwnProperty } from "./object.js";
+
 /**
  * Returns an ArrayBuffer generated from the provided Base64.
  *
@@ -17,7 +19,7 @@ export const a2b = ($, ...$s) => {
   const source = (
     typeof $ == "string"
       ? $
-      : Object.hasOwn($, "raw")
+      : hasOwnProperty($, "raw")
       ? String.raw($, ...$s)
       : `${$}`
   ).replace(/[\t\n\f\r ]+/gu, "");
@@ -82,8 +84,7 @@ export const a2b = ($, ...$s) => {
 export const b2a = ($, ...$s) => {
   const buffer = $ instanceof ArrayBuffer
     ? $
-    : $ instanceof DataView ||
-        $ instanceof Object.getPrototypeOf(Uint8Array)
+    : $ instanceof DataView || $ instanceof getPrototype(Uint8Array)
     ? $.buffer
     : ((string) =>
       Array.prototype.reduce.call(
index 69206613a13a492758e9300b326a531d97d95c7f..10172e643b29fbe5b0dc741f531fc28d1f9f4875 100644 (file)
@@ -8,7 +8,7 @@
 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
 
 import { MAX_SAFE_INTEGER } from "./numeric.js";
-import { isObject } from "./object.js";
+import { isObject, sameValue } from "./object.js";
 
 /**
  * Returns -0 if the provided argument is "-0"; returns a number
@@ -33,7 +33,7 @@ export const canonicalNumericIndexString = ($) => {
 export const isArrayIndex = ($) => {
   const value = canonicalNumericIndexString($);
   if (value !== undefined) {
-    return Object.is(value, 0) || value > 0 && value < -1 >>> 0;
+    return sameValue(value, 0) || value > 0 && value < -1 >>> 0;
   } else {
     return false;
   }
@@ -89,7 +89,7 @@ export const isConcatSpreadable = ($) => {
 export const isIntegerIndex = ($) => {
   const value = canonicalNumericIndexString($);
   if (value !== undefined) {
-    return Object.is(value, 0) ||
+    return sameValue(value, 0) ||
       value > 0 && value <= MAX_SAFE_INTEGER;
   } else {
     return false;
diff --git a/function.js b/function.js
new file mode 100644 (file)
index 0000000..0b9ebcc
--- /dev/null
@@ -0,0 +1,89 @@
+// ♓🌟 Piscēs ∷ function.js
+// ====================================================================
+//
+// Copyright © 2022 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 { defineOwnProperty, isObject } from "./object.js";
+
+/**
+ * Creates a bound function from the provided function using the
+ * provided this value and arguments list.
+ *
+ * ☡ As with call and construct, the arguments must be passed as an
+ * array.
+ */
+export const bind = (() => {
+  const callBind = Function.prototype.call.bind(
+    Function.prototype.bind,
+  );
+  const bind = ($, boundThis, boundArgs) =>
+    callBind($, boundThis, ...boundArgs);
+  return bind;
+})();
+
+/**
+ * Calls the provided function with the provided this value and
+ * arguments list.
+ *
+ * ☡ This is an alias for Reflect.apply—the arguments must be passed
+ * as an array.
+ */
+export const call = Reflect.apply;
+
+/**
+ * Constructs the provided function with the provided arguments list
+ * and new target.
+ *
+ * ☡ This is an alias for Reflect.construct—the arguments must be
+ * passed as an array.
+ */
+export const construct = Reflect.construct;
+
+/** Returns whether the provided value is a constructor. */
+export const isConstructor = ($) => {
+  if (!isObject($)) {
+    // The provided value is not an object.
+    return false;
+  } else {
+    // The provided value is an object.
+    try {
+      construct(
+        function () {},
+        [],
+        $,
+      ); // will throw if $ is not a constructor
+      return true;
+    } catch {
+      return false;
+    }
+  }
+};
+
+/**
+ * Returns a new function which calls the provided function with its
+ * first argument as the `this` value and the remaining arguments
+ * passed through.
+ *
+ * ※ This is effectively an alias for Function.prototype.call.bind.
+ */
+export const makeCallable = (() => {
+       const functionCall = Function.prototype.call;
+       const callable = ($) => defineOwnProperty(
+               bind(functionCall, $, []),
+               "length",
+               { value: $.length + 1 },
+       );
+       return callable;
+})();
+
+/**
+ * Returns whether the provided object inherits from the prototype of
+ * the provided function.
+ */
+export const ordinaryHasInstance = makeCallable(
+       Function.prototype[Symbol.hasInstance],
+);
diff --git a/iri.js b/iri.js
index b9682d96e91d0fc8754b66544da0a1b20166f455..a3e454689346b998df91fb413316af89219ef033 100644 (file)
--- a/iri.js
+++ b/iri.js
@@ -7,6 +7,13 @@
 // 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 } from "./function.js";
+import {
+  defineOwnProperties,
+  namedEntries,
+  objectFromEntries,
+} from "./object.js";
+
 const sub·delims = String.raw`[!\$&'()*+,;=]`;
 const gen·delims = String.raw`[:/?#\[\]@]`;
 //deno-lint-ignore no-unused-vars
@@ -167,8 +174,8 @@ export const {
   isLEIRIPath,
   isLEIRIReference,
   isLEIRISuffix, // only authority, path, query, fragment
-} = Object.fromEntries(
-  Object.entries({
+} = objectFromEntries(
+  namedEntries({
     isAbsoluteLEIRI: absolute·LEIRI,
     isAbsoluteIRI: absolute·IRI,
     isAbsoluteURI: absolute·URI,
@@ -191,14 +198,14 @@ export const {
     const regExp = new RegExp(`^(?:${value})$`, "u");
     return [
       key,
-      Object.defineProperties(
+      defineOwnProperties(
         ($) => typeof $ == "string" && regExp.test($),
         {
           name: { value: key },
           [Symbol.match]: {
             configurable: true,
             enumerable: false,
-            get: () => regExp[Symbol.match].bind(regExp),
+            get: () => bind(regExp[Symbol.match], regExp, []),
             set: undefined,
           },
         },
@@ -266,8 +273,8 @@ export const escapeForIRI = ($) => {
   // Escape disallowed codepoints in each component and compose an
   // I·R·I from the result.
   return composeReference(
-    Object.fromEntries(
-      Object.entries(components).map(
+    objectFromEntries(
+      namedEntries(components).map(
         ([componentName, componentValue]) => [
           componentName,
           componentValue == null ? undefined : [...function* () {
diff --git a/mod.js b/mod.js
index 9dd8fd1192936b735214a3a427cf0fb09cfd740d..d036cbc220f4c970d80aee972071d6e8cb2bde86 100644 (file)
--- a/mod.js
+++ b/mod.js
@@ -9,6 +9,7 @@
 
 export * from "./base64.js";
 export * from "./collection.js";
+export * from "./function.js";
 export * from "./iri.js";
 export * from "./numeric.js";
 export * from "./object.js";
index 8f5c4903882ce1fd4b3561cac44c2ce4edd19553..c0a9081ad1880f069b459819b331c6695588eed2 100644 (file)
--- a/object.js
+++ b/object.js
@@ -7,6 +7,41 @@
 // 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 { call } from "./function.js";
+
+export const {
+  assign: assignProperties,
+  defineProperty: defineOwnProperty,
+  defineProperties: defineOwnProperties,
+  freeze,
+  getOwnPropertyDescriptor,
+  getOwnPropertyDescriptors,
+  getOwnPropertyNames: getOwnPropertyStrings,
+  getOwnPropertySymbols,
+  getPrototypeOf: getPrototype,
+  hasOwn: hasOwnProperty,
+  isExtensible,
+  isFrozen,
+  isSealed,
+  entries: namedEntries,
+  keys: namedKeys,
+  values: namedValues,
+  create: objectCreate,
+  fromEntries: objectFromEntries,
+  preventExtensions,
+  is: sameValue,
+  seal,
+  setPrototypeOf: setPrototype,
+} = Object;
+
+export const {
+  delete: deleteOwnProperty,
+  keys: getOwnPropertyKeys,
+  get: getPropertyValue,
+  has: hasProperty,
+  set: setPropertyValue,
+} = Reflect;
+
 /**
  * A property descriptor object.
  *
@@ -37,7 +72,7 @@ export const PropertyDescriptor = (() => {
         );
       } else {
         // The provided value is an object.
-        const desc = Object.create(propertyDescriptorPrototype);
+        const desc = objectCreate(propertyDescriptorPrototype);
         if ("enumerable" in Obj) {
           // An enumerable property is specified.
           desc.enumerable = !!Obj.enumerable;
@@ -228,8 +263,8 @@ export const PropertyDescriptor = (() => {
 
   const propertyDescriptorPrototype = PropertyDescriptor.prototype;
 
-  const propertyDescriptorProxyHandler = Object.assign(
-    Object.create(null),
+  const propertyDescriptorProxyHandler = assignProperties(
+    objectCreate(null),
     {
       defineProperty(O, P, Desc) {
         if (
@@ -264,11 +299,11 @@ export const PropertyDescriptor = (() => {
             );
           } else {
             // P can be safely defined on O.
-            return Reflect.defineProperty(O, P, desc);
+            return defineOwnProperty(O, P, desc);
           }
         } else {
           // P is not a property descriptor attribute.
-          return Reflect.defineProperty(O, P, Desc);
+          return defineOwnProperty(O, P, Desc);
         }
       },
       set(O, P, V, Receiver) {
@@ -285,7 +320,7 @@ export const PropertyDescriptor = (() => {
           );
         } else {
           // P can be safely defined on O.
-          return Reflect.set(O, prop, newValue, Receiver);
+          return setPropertyValue(O, prop, newValue, Receiver);
         }
       },
       setPrototypeOf(O, V) {
@@ -294,7 +329,7 @@ export const PropertyDescriptor = (() => {
           return false;
         } else {
           // V is the property descriptor prototype.
-          return Reflect.setPrototypeOf(O, V);
+          return setPrototype(O, V);
         }
       },
     },
@@ -331,15 +366,15 @@ export const frozenCopy = (O, constructor = O?.constructor) => {
     // (If not provided, the constructor will be the value of getting
     // the `constructor` property of O.)
     const species = constructor?.[Symbol.species] ?? constructor;
-    return Object.preventExtensions(
-      Object.create(
+    return preventExtensions(
+      objectCreate(
         species == null || !("prototype" in species)
           ? null
           : species.prototype,
-        Object.fromEntries(
+        objectFromEntries(
           function* () {
-            for (const P of Reflect.ownKeys(O)) {
-              const Desc = Object.getOwnPropertyDescriptor(O, P);
+            for (const P of getOwnPropertyKeys(O)) {
+              const Desc = getOwnPropertyDescriptor(O, P);
               if (Desc.enumerable) {
                 // P is an enumerable property.
                 yield [
@@ -370,40 +405,12 @@ export const frozenCopy = (O, constructor = O?.constructor) => {
   }
 };
 
-/** Returns whether the provided value is a constructor. */
-export const isConstructor = ($) => {
-  if (!isObject($)) {
-    // The provided value is not an object.
-    return false;
-  } else {
-    // The provided value is an object.
-    try {
-      Reflect.construct(
-        function () {},
-        [],
-        $,
-      ); // will throw if $ is not a constructor
-      return true;
-    } catch {
-      return false;
-    }
-  }
-};
-
 /** Returns whether the provided value is an object. */
 export const isObject = ($) => {
   return $ !== null &&
     (typeof $ == "function" || typeof $ == "object");
 };
 
-/**
- * Returns whether the provided object inherits from the prototype of
- * the provided function.
- */
-export const ordinaryHasInstance = Function.prototype.call.bind(
-  Function.prototype[Symbol.hasInstance],
-);
-
 /**
  * Returns the primitive value of the provided object per its
  * `toString` and `valueOf` methods.
@@ -423,7 +430,7 @@ export const ordinaryToPrimitive = (O, hint) => {
     const method = O[name];
     if (typeof method == "function") {
       // Method is callable.
-      const result = method.call(O);
+      const result = call(method, O, []);
       if (!isObject(result)) {
         // Method returns a primitive.
         return result;
@@ -470,7 +477,7 @@ export const toPrimitive = ($, preferredType) => {
           );
         } else {
           // The resulting hint is either default, string, or number.
-          return exoticToPrim.call($, hint);
+          return call(exoticToPrim, $, [hint]);
         }
       }
     } else {
This page took 0.084043 seconds and 4 git commands to generate.