]> Lady’s Gitweb - Pisces/commitdiff
Move index string functions back into value.js
authorLady <redacted>
Sun, 27 Jul 2025 18:26:41 +0000 (14:26 -0400)
committerLady <redacted>
Sun, 27 Jul 2025 18:26:41 +0000 (14:26 -0400)
While index strings are always strings, really they are special kinds
of values, and `canonicalNumericIndexString` notably does not return a
string but rather a number or undefined. Since `toLength` needs to be
in `value.js`, and these functions are very similar in function and
applicability, it seems best to keep them in the same place.

string.js
string.test.js
value.js
value.test.js

index ddc05d7d71ee6f479c2153596542d8cba9554a03..99528a8c2c88f7c032a37e3a5bd472145ce4dbb5 100644 (file)
--- a/string.js
+++ b/string.js
@@ -345,25 +345,6 @@ export const {
   };
 })();
 
-/**
- * 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;
-  }
-};
-
 export const {
   /**
    * Returns an iterator over the codepoints in the string representation
@@ -548,36 +529,6 @@ export const getLastSubstringIndex = createCallableFunction(
   { name: "getLastSubstringIndex" },
 );
 
-/** 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;
-  }
-};
-
-/** 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;
-  }
-};
-
 /**
  * Returns the result of joining the provided iterable.
  *
index 147e109c6ee692b07cf9f7dfb21d5a2118fe2293..e567060f81bac2fcf1efa427e5798c49e3a3098b 100644 (file)
@@ -23,7 +23,6 @@ import {
 import {
   asciiLowercase,
   asciiUppercase,
-  canonicalNumericIndexString,
   characters,
   codepoints,
   codeUnits,
@@ -32,8 +31,6 @@ import {
   getCodeUnit,
   getFirstSubstringIndex,
   getLastSubstringIndex,
-  isArrayIndexString,
-  isIntegerIndexString,
   join,
   Matcher,
   rawString,
@@ -635,59 +632,6 @@ describe("asciiUppercase", () => {
   });
 });
 
-describe("canonicalNumericIndexString", () => {
-  it("[[Call]] returns undefined for nonstrings", () => {
-    assertStrictEquals(canonicalNumericIndexString(1), void {});
-  });
-
-  it("[[Call]] returns undefined for noncanonical strings", () => {
-    assertStrictEquals(canonicalNumericIndexString(""), void {});
-    assertStrictEquals(canonicalNumericIndexString("01"), void {});
-    assertStrictEquals(
-      canonicalNumericIndexString("9007199254740993"),
-      void {},
-    );
-  });
-
-  it('[[Call]] returns -0 for "-0"', () => {
-    assertStrictEquals(canonicalNumericIndexString("-0"), -0);
-  });
-
-  it("[[Call]] returns the corresponding number for canonical strings", () => {
-    assertStrictEquals(canonicalNumericIndexString("0"), 0);
-    assertStrictEquals(canonicalNumericIndexString("-0.25"), -0.25);
-    assertStrictEquals(
-      canonicalNumericIndexString("9007199254740992"),
-      9007199254740992,
-    );
-    assertStrictEquals(canonicalNumericIndexString("NaN"), 0 / 0);
-    assertStrictEquals(canonicalNumericIndexString("Infinity"), 1 / 0);
-    assertStrictEquals(
-      canonicalNumericIndexString("-Infinity"),
-      -1 / 0,
-    );
-  });
-
-  it("[[Construct]] throws an error", () => {
-    assertThrows(() => new canonicalNumericIndexString(""));
-  });
-
-  describe(".length", () => {
-    it("[[Get]] returns the correct length", () => {
-      assertStrictEquals(canonicalNumericIndexString.length, 1);
-    });
-  });
-
-  describe(".name", () => {
-    it("[[Get]] returns the correct name", () => {
-      assertStrictEquals(
-        canonicalNumericIndexString.name,
-        "canonicalNumericIndexString",
-      );
-    });
-  });
-});
-
 describe("characters", () => {
   it("[[Call]] returns an iterable", () => {
     assertStrictEquals(
@@ -1008,131 +952,6 @@ describe("getLastSubstringIndex", () => {
   });
 });
 
-describe("isArrayIndexString", () => {
-  it("[[Call]] returns false for nonstrings", () => {
-    assertStrictEquals(isArrayIndexString(1), false);
-  });
-
-  it("[[Call]] returns false for noncanonical strings", () => {
-    assertStrictEquals(isArrayIndexString(""), false);
-    assertStrictEquals(isArrayIndexString("01"), false);
-    assertStrictEquals(isArrayIndexString("9007199254740993"), false);
-  });
-
-  it("[[Call]] returns false for nonfinite numbers", () => {
-    assertStrictEquals(isArrayIndexString("NaN"), false);
-    assertStrictEquals(isArrayIndexString("Infinity"), false);
-    assertStrictEquals(isArrayIndexString("-Infinity"), false);
-  });
-
-  it("[[Call]] returns false for negative numbers", () => {
-    assertStrictEquals(isArrayIndexString("-0"), false);
-    assertStrictEquals(isArrayIndexString("-1"), false);
-  });
-
-  it("[[Call]] returns false for nonintegers", () => {
-    assertStrictEquals(isArrayIndexString("0.25"), false);
-    assertStrictEquals(isArrayIndexString("1.1"), false);
-  });
-
-  it("[[Call]] returns false for numbers greater than or equal to -1 >>> 0", () => {
-    assertStrictEquals(isArrayIndexString(String(-1 >>> 0)), false);
-    assertStrictEquals(
-      isArrayIndexString(String((-1 >>> 0) + 1)),
-      false,
-    );
-  });
-
-  it("[[Call]] returns true for array lengths less than -1 >>> 0", () => {
-    assertStrictEquals(isArrayIndexString("0"), true);
-    assertStrictEquals(
-      isArrayIndexString(String((-1 >>> 0) - 1)),
-      true,
-    );
-  });
-
-  it("[[Construct]] throws an error", () => {
-    assertThrows(() => new isArrayIndexString("0"));
-  });
-
-  describe(".length", () => {
-    it("[[Get]] returns the correct length", () => {
-      assertStrictEquals(isArrayIndexString.length, 1);
-    });
-  });
-
-  describe(".name", () => {
-    it("[[Get]] returns the correct name", () => {
-      assertStrictEquals(
-        isArrayIndexString.name,
-        "isArrayIndexString",
-      );
-    });
-  });
-});
-
-describe("isIntegerIndexString", () => {
-  it("[[Call]] returns false for nonstrings", () => {
-    assertStrictEquals(isIntegerIndexString(1), false);
-  });
-
-  it("[[Call]] returns false for noncanonical strings", () => {
-    assertStrictEquals(isIntegerIndexString(""), false);
-    assertStrictEquals(isIntegerIndexString("01"), false);
-    assertStrictEquals(
-      isIntegerIndexString("9007199254740993"),
-      false,
-    );
-  });
-
-  it("[[Call]] returns false for nonfinite numbers", () => {
-    assertStrictEquals(isIntegerIndexString("NaN"), false);
-    assertStrictEquals(isIntegerIndexString("Infinity"), false);
-    assertStrictEquals(isIntegerIndexString("-Infinity"), false);
-  });
-
-  it("[[Call]] returns false for negative numbers", () => {
-    assertStrictEquals(isIntegerIndexString("-0"), false);
-    assertStrictEquals(isIntegerIndexString("-1"), false);
-  });
-
-  it("[[Call]] returns false for nonintegers", () => {
-    assertStrictEquals(isIntegerIndexString("0.25"), false);
-    assertStrictEquals(isIntegerIndexString("1.1"), false);
-  });
-
-  it("[[Call]] returns false for numbers greater than or equal to 2 ** 53", () => {
-    assertStrictEquals(
-      isIntegerIndexString("9007199254740992"),
-      false,
-    );
-  });
-
-  it("[[Call]] returns true for safe canonical integer strings", () => {
-    assertStrictEquals(isIntegerIndexString("0"), true);
-    assertStrictEquals(isIntegerIndexString("9007199254740991"), true);
-  });
-
-  it("[[Construct]] throws an error", () => {
-    assertThrows(() => new isIntegerIndexString("0"));
-  });
-
-  describe(".length", () => {
-    it("[[Get]] returns the correct length", () => {
-      assertStrictEquals(isIntegerIndexString.length, 1);
-    });
-  });
-
-  describe(".name", () => {
-    it("[[Get]] returns the correct name", () => {
-      assertStrictEquals(
-        isIntegerIndexString.name,
-        "isIntegerIndexString",
-      );
-    });
-  });
-});
-
 describe("join", () => {
   it("[[Call]] joins the provided iterator with the provided separartor", () => {
     assertStrictEquals(join([1, 2, 3, 4].values(), "☂"), "1☂2☂3☂4");
index 6956b6fc6d45945e52f5234ae43b35ebb3d73da3..341ecdf9dd492653f0397d31317c424c98dc12af 100644 (file)
--- a/value.js
+++ b/value.js
@@ -178,6 +178,25 @@ export const POSITIVE_ZERO = 0;
 /** The undefined primitive. */
 export const UNDEFINED = undefined;
 
+/**
+ * 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.
@@ -243,6 +262,21 @@ export const completePropertyDescriptor = (Desc) => {
 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);
@@ -266,6 +300,21 @@ export const isGenericDescriptor = (Desc) =>
   && !("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;
+  }
+};
+
 export const {
   /**
    * Returns the primitive value of the provided object per its
@@ -420,7 +469,7 @@ export const {
   const { isNaN: isNan } = Number;
   const { is } = Object;
   return {
-    sameValue: (a, b) => is(a, b),
+    sameValue: ($1, $2) => is($1, $2),
     sameValueZero: ($1, $2) => {
       const type1 = type($1);
       const type2 = type($2);
index b7dcd6980e89c4c12bac9b6fd861562c4707598c..c55b591eb97c64ca9f5d6b83147067cc1a063829 100644 (file)
@@ -19,13 +19,16 @@ import {
 } from "./dev-deps.js";
 import {
   ASYNC_ITERATOR,
+  canonicalNumericIndexSting,
   completePropertyDescriptor,
   HAS_INSTANCE,
   IS_CONCAT_SPREADABLE,
   isAccessorDescriptor,
+  isArrayIndexString,
   isDataDescriptor,
   isFullyPopulatedDescriptor,
   isGenericDescriptor,
+  isIntegerIndexString,
   ITERATOR,
   LN_10,
   LN_2,
@@ -249,6 +252,59 @@ describe("UNSCOPABLES", () => {
   });
 });
 
+describe("canonicalNumericIndexString", () => {
+  it("[[Call]] returns undefined for nonstrings", () => {
+    assertStrictEquals(canonicalNumericIndexString(1), void {});
+  });
+
+  it("[[Call]] returns undefined for noncanonical strings", () => {
+    assertStrictEquals(canonicalNumericIndexString(""), void {});
+    assertStrictEquals(canonicalNumericIndexString("01"), void {});
+    assertStrictEquals(
+      canonicalNumericIndexString("9007199254740993"),
+      void {},
+    );
+  });
+
+  it('[[Call]] returns -0 for "-0"', () => {
+    assertStrictEquals(canonicalNumericIndexString("-0"), -0);
+  });
+
+  it("[[Call]] returns the corresponding number for canonical strings", () => {
+    assertStrictEquals(canonicalNumericIndexString("0"), 0);
+    assertStrictEquals(canonicalNumericIndexString("-0.25"), -0.25);
+    assertStrictEquals(
+      canonicalNumericIndexString("9007199254740992"),
+      9007199254740992,
+    );
+    assertStrictEquals(canonicalNumericIndexString("NaN"), 0 / 0);
+    assertStrictEquals(canonicalNumericIndexString("Infinity"), 1 / 0);
+    assertStrictEquals(
+      canonicalNumericIndexString("-Infinity"),
+      -1 / 0,
+    );
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new canonicalNumericIndexString(""));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(canonicalNumericIndexString.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        canonicalNumericIndexString.name,
+        "canonicalNumericIndexString",
+      );
+    });
+  });
+});
+
 describe("completePropertyDescriptor", () => {
   it("[[Call]] completes a generic descriptor", () => {
     const desc = {};
@@ -352,6 +408,69 @@ describe("isAccessorDescriptor", () => {
   });
 });
 
+describe("isArrayIndexString", () => {
+  it("[[Call]] returns false for nonstrings", () => {
+    assertStrictEquals(isArrayIndexString(1), false);
+  });
+
+  it("[[Call]] returns false for noncanonical strings", () => {
+    assertStrictEquals(isArrayIndexString(""), false);
+    assertStrictEquals(isArrayIndexString("01"), false);
+    assertStrictEquals(isArrayIndexString("9007199254740993"), false);
+  });
+
+  it("[[Call]] returns false for nonfinite numbers", () => {
+    assertStrictEquals(isArrayIndexString("NaN"), false);
+    assertStrictEquals(isArrayIndexString("Infinity"), false);
+    assertStrictEquals(isArrayIndexString("-Infinity"), false);
+  });
+
+  it("[[Call]] returns false for negative numbers", () => {
+    assertStrictEquals(isArrayIndexString("-0"), false);
+    assertStrictEquals(isArrayIndexString("-1"), false);
+  });
+
+  it("[[Call]] returns false for nonintegers", () => {
+    assertStrictEquals(isArrayIndexString("0.25"), false);
+    assertStrictEquals(isArrayIndexString("1.1"), false);
+  });
+
+  it("[[Call]] returns false for numbers greater than or equal to -1 >>> 0", () => {
+    assertStrictEquals(isArrayIndexString(String(-1 >>> 0)), false);
+    assertStrictEquals(
+      isArrayIndexString(String((-1 >>> 0) + 1)),
+      false,
+    );
+  });
+
+  it("[[Call]] returns true for array lengths less than -1 >>> 0", () => {
+    assertStrictEquals(isArrayIndexString("0"), true);
+    assertStrictEquals(
+      isArrayIndexString(String((-1 >>> 0) - 1)),
+      true,
+    );
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isArrayIndexString("0"));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isArrayIndexString.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isArrayIndexString.name,
+        "isArrayIndexString",
+      );
+    });
+  });
+});
+
 describe("isDataDescriptor", () => {
   it("[[Call]] returns false for a generic descriptor", () => {
     assertStrictEquals(isDataDescriptor({}), false);
@@ -505,6 +624,68 @@ describe("isGenericDescriptor", () => {
   });
 });
 
+describe("isIntegerIndexString", () => {
+  it("[[Call]] returns false for nonstrings", () => {
+    assertStrictEquals(isIntegerIndexString(1), false);
+  });
+
+  it("[[Call]] returns false for noncanonical strings", () => {
+    assertStrictEquals(isIntegerIndexString(""), false);
+    assertStrictEquals(isIntegerIndexString("01"), false);
+    assertStrictEquals(
+      isIntegerIndexString("9007199254740993"),
+      false,
+    );
+  });
+
+  it("[[Call]] returns false for nonfinite numbers", () => {
+    assertStrictEquals(isIntegerIndexString("NaN"), false);
+    assertStrictEquals(isIntegerIndexString("Infinity"), false);
+    assertStrictEquals(isIntegerIndexString("-Infinity"), false);
+  });
+
+  it("[[Call]] returns false for negative numbers", () => {
+    assertStrictEquals(isIntegerIndexString("-0"), false);
+    assertStrictEquals(isIntegerIndexString("-1"), false);
+  });
+
+  it("[[Call]] returns false for nonintegers", () => {
+    assertStrictEquals(isIntegerIndexString("0.25"), false);
+    assertStrictEquals(isIntegerIndexString("1.1"), false);
+  });
+
+  it("[[Call]] returns false for numbers greater than or equal to 2 ** 53", () => {
+    assertStrictEquals(
+      isIntegerIndexString("9007199254740992"),
+      false,
+    );
+  });
+
+  it("[[Call]] returns true for safe canonical integer strings", () => {
+    assertStrictEquals(isIntegerIndexString("0"), true);
+    assertStrictEquals(isIntegerIndexString("9007199254740991"), true);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isIntegerIndexString("0"));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isIntegerIndexString.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isIntegerIndexString.name,
+        "isIntegerIndexString",
+      );
+    });
+  });
+});
+
 describe("ordinaryToPrimitive", () => {
   it("[[Call]] prefers `valueOf` by default", () => {
     const obj = {
This page took 0.246113 seconds and 4 git commands to generate.