+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(getFirstSubstringIndex.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ getFirstSubstringIndex.name,
+ "getFirstSubstringIndex",
+ );
+ });
+ });
+});
+
+describe("getLastSubstringIndex", () => {
+ it("[[Call]] returns the index of the first match", () => {
+ assertStrictEquals(getLastSubstringIndex("Ii🎙🆗☺🆗", "🆗"), 7);
+ });
+
+ it("[[Call]] returns −1 if no match is found", () => {
+ assertStrictEquals(getLastSubstringIndex("Ii🎙🆗☺🆗", "🆖🆗"), -1);
+ });
+
+ it("[[Call]] returns the length when provided with an empty string", () => {
+ assertStrictEquals(
+ getLastSubstringIndex("Ii🎙🆗☺🆗", ""),
+ "Ii🎙🆗☺🆗".length,
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new getLastSubstringIndex("", ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(getLastSubstringIndex.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ getLastSubstringIndex.name,
+ "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");
+ });
+
+ it('[[Call]] uses "," if no separator is provided', () => {
+ assertStrictEquals(join([1, 2, 3, 4].values()), "1,2,3,4");
+ });
+
+ it("[[Call]] uses the empty sting for nullish values", () => {
+ assertStrictEquals(
+ join([null, , null, undefined].values(), "☂"),
+ "☂☂☂",
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new join([]));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(join.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(join.name, "join");
+ });
+ });
+});
+
+describe("rawString", () => {
+ it("[[Call]] acts like String.raw", () => {
+ assertStrictEquals(rawString`\nraw${" string"}`, "\\nraw string");
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new rawString(["string"]));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(rawString.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(rawString.name, "rawString");
+ });
+ });
+});
+
+describe("scalarValues", () => {
+ it("[[Call]] returns an iterable", () => {
+ assertStrictEquals(
+ typeof scalarValues("")[Symbol.iterator],
+ "function",
+ );
+ });
+
+ it("[[Call]] returns an iterator", () => {
+ assertStrictEquals(typeof scalarValues("").next, "function");
+ });
+
+ it("[[Call]] returns a string scalar value iterator", () => {
+ assertStrictEquals(
+ scalarValues("")[Symbol.toStringTag],
+ "String Scalar Value Iterator",
+ );
+ });
+
+ it("[[Call]] iterates over the scalar values", () => {
+ assertEquals([
+ ...scalarValues("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
+ ], [
+ 0x49,
+ 0x69,
+ 0x1F399,
+ 0xFFFD,
+ 0xFFFD,
+ 0xFFFD,
+ 0xFFFD,
+ 0x1F197,
+ 0x263A,
+ ]);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new scalarValues(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(scalarValues.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(scalarValues.name, "scalarValues");
+ });
+ });
+});
+
+describe("splitOnAsciiWhitespace", () => {
+ it("[[Call]] splits on sequences of spaces", () => {
+ assertEquals(
+ splitOnAsciiWhitespace("🅰️ 🅱️ 🆎 🅾️"),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ });
+
+ it("[[Call]] splits on sequences of tabs", () => {
+ assertEquals(
+ splitOnAsciiWhitespace("🅰️\t\t\t🅱️\t🆎\t\t🅾️"),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ });
+
+ it("[[Call]] splits on sequences of carriage returns", () => {
+ assertEquals(
+ splitOnAsciiWhitespace("🅰️\r\r\r🅱️\r🆎\r\r🅾️"),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ });
+
+ it("[[Call]] splits on sequences of newlines", () => {
+ assertEquals(
+ splitOnAsciiWhitespace("🅰️\r\r\r🅱️\r🆎\r\r🅾️"),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ });
+
+ it("[[Call]] splits on sequences of form feeds", () => {
+ assertEquals(
+ splitOnAsciiWhitespace("🅰️\f\f\f🅱️\f🆎\f\f🅾️"),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ });
+
+ it("[[Call]] splits on mixed whitespace", () => {
+ assertEquals(
+ splitOnAsciiWhitespace("🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️"),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ });
+
+ it("[[Call]] returns an array of just the empty string for the empty string", () => {
+ assertEquals(splitOnAsciiWhitespace(""), [""]);
+ });
+
+ it("[[Call]] returns a single token if there are no spaces", () => {
+ assertEquals(splitOnAsciiWhitespace("abcd"), ["abcd"]);
+ });
+
+ it("[[Call]] does not split on other kinds of whitespace", () => {
+ assertEquals(
+ splitOnAsciiWhitespace("a\u202F\u205F\xa0\v\0\bb"),
+ ["a\u202F\u205F\xa0\v\0\bb"],
+ );
+ });
+
+ it("[[Call]] trims leading and trailing whitespace", () => {
+ assertEquals(
+ splitOnAsciiWhitespace(
+ "\f\r\n\r\n \n\t🅰️\f \t\n🅱️\r🆎\n\f🅾️\n\f",
+ ),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new splitOnAsciiWhitespace(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(splitOnAsciiWhitespace.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ splitOnAsciiWhitespace.name,
+ "splitOnAsciiWhitespace",
+ );
+ });
+ });
+});
+
+describe("splitOnCommas", () => {
+ it("[[Call]] splits on commas", () => {
+ assertEquals(
+ splitOnCommas("🅰️,🅱️,🆎,🅾️"),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ });
+
+ it("[[Call]] returns an array of just the empty string for the empty string", () => {
+ assertEquals(splitOnCommas(""), [""]);
+ });
+
+ it("[[Call]] returns a single token if there are no commas", () => {
+ assertEquals(splitOnCommas("abcd"), ["abcd"]);
+ });
+
+ it("[[Call]] splits into empty strings if there are only commas", () => {
+ assertEquals(splitOnCommas(",,,"), ["", "", "", ""]);
+ });
+
+ it("[[Call]] trims leading and trailing whitespace", () => {
+ assertEquals(
+ splitOnCommas("\f\r\n\r\n \n\t🅰️,🅱️,🆎,🅾️\n\f"),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ assertEquals(
+ splitOnCommas("\f\r\n\r\n \n\t,,,\n\f"),
+ ["", "", "", ""],
+ );
+ });
+
+ it("[[Call]] removes whitespace from the split tokens", () => {
+ assertEquals(
+ splitOnCommas(
+ "\f\r\n\r\n \n\t🅰️\f , \t\n🅱️,\r\n\r🆎\n\f,🅾️\n\f",
+ ),
+ ["🅰️", "🅱️", "🆎", "🅾️"],
+ );
+ assertEquals(
+ splitOnCommas("\f\r\n\r\n \n\t\f , \t\n,\r\n\r\n\f,\n\f"),
+ ["", "", "", ""],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new splitOnCommas(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(splitOnCommas.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(splitOnCommas.name, "splitOnCommas");
+ });
+ });
+});
+
+describe("stringCatenate", () => {
+ it("[[Call]] catenates the values", () => {
+ assertStrictEquals(stringCatenate("the", " values"), "the values");
+ });
+
+ it("[[Call]] returns an empty string when called with no values", () => {
+ assertStrictEquals(stringCatenate(), "");
+ });
+
+ it('[[Call]] uses "undefined" when explicitly provided undefined', () => {
+ assertStrictEquals(
+ stringCatenate(undefined, undefined),
+ "undefinedundefined",
+ );
+ });
+
+ it('[[Call]] uses "null" when provided null', () => {
+ assertStrictEquals(stringCatenate(null, null), "nullnull");
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringCatenate());
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringCatenate.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringCatenate.name, "stringCatenate");
+ });
+ });
+});
+
+describe("stringEndsWith", () => {
+ it("[[Call]] returns whether the string ends with the thing", () => {
+ assertStrictEquals(
+ stringEndsWith("very success", " success"),
+ true,
+ );
+ assertStrictEquals(stringEndsWith("very fail", " success"), false);
+ });
+
+ it("[[Call]] accepts an offset", () => {
+ assertStrictEquals(
+ stringEndsWith("very successful", " success", 12),
+ true,
+ );
+ });
+
+ it("[[Call]] returns true for an empty string test", () => {
+ assertStrictEquals(stringEndsWith("", ""), true);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringEndsWith("", ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringEndsWith.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringEndsWith.name, "stringEndsWith");
+ });
+ });
+});
+
+describe("stringFromCodeUnits", () => {
+ it("[[Call]] makes the string", () => {
+ assertStrictEquals(
+ stringFromCodeUnits(0xD83C, 0xDD97),
+ "🆗",
+ );
+ });
+
+ it("[[Call]] throws with non‐integral arguments", () => {
+ assertThrows(() => stringFromCodeUnits(NaN));
+ assertThrows(() => stringFromCodeUnits(Infinity));
+ assertThrows(() => stringFromCodeUnits(0.1));
+ });
+
+ it("[[Call]] throws with arguments out of range", () => {
+ assertThrows(() => stringFromCodeUnits(-1));
+ assertThrows(() => stringFromCodeUnits(0x10000));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringFromCodeUnits([]));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringFromCodeUnits.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ stringFromCodeUnits.name,
+ "stringFromCodeUnits",
+ );
+ });
+ });
+});
+
+describe("stringFromCodepoints", () => {
+ it("[[Call]] makes the string", () => {
+ assertStrictEquals(stringFromCodepoints(0x1F197), "🆗");
+ });
+
+ it("[[Call]] throws with non‐integral arguments", () => {
+ assertThrows(() => stringFromCodepoints(NaN));
+ assertThrows(() => stringFromCodepoints(Infinity));
+ assertThrows(() => stringFromCodepoints(0.1));
+ });
+
+ it("[[Call]] throws with arguments out of range", () => {
+ assertThrows(() => stringFromCodepoints(-1));
+ assertThrows(() => stringFromCodepoints(0x110000));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringFromCodepoints([]));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringFromCodepoints.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ stringFromCodepoints.name,
+ "stringFromCodepoints",
+ );
+ });
+ });
+});
+
+describe("stringIncludes", () => {
+ it("[[Call]] returns whether the string includes the thing", () => {
+ assertStrictEquals(
+ stringIncludes("very success full", " success "),
+ true,
+ );
+ assertStrictEquals(
+ stringIncludes("very fail full", " success "),
+ false,
+ );
+ });
+
+ it("[[Call]] accepts an offset", () => {
+ assertStrictEquals(
+ stringIncludes("maybe success full", " success ", 4),
+ true,
+ );
+ assertStrictEquals(
+ stringIncludes("maybe success full", " success ", 5),
+ true,
+ );
+ assertStrictEquals(
+ stringIncludes("maybe success full", " success ", 6),
+ false,
+ );
+ });
+
+ it("[[Call]] returns true for an empty string test", () => {
+ assertStrictEquals(stringIncludes("", ""), true);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringIncludes("", ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringIncludes.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringIncludes.name, "stringIncludes");
+ });
+ });
+});
+
+describe("stringMatch", () => {
+ it("[[Call]] does the match akin to String::match", () => {
+ assertEquals(
+ [...stringMatch("very success full", /([sc]+[ue]?)+/)],
+ ["success", "ss"],
+ );
+ assertEquals(
+ [...stringMatch("very success full", /([sc]+)[ue]?/g)],
+ ["su", "cce", "ss"],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringMatch("", /(?:)/));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringMatch.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringMatch.name, "stringMatch");
+ });
+ });
+});
+
+describe("stringMatchAll", () => {
+ it("[[Call]] does the match akin to String::matchAll", () => {
+ assertEquals(
+ [...stringMatchAll("very success full", /([sc]+)[ue]?/g)].map((
+ match,
+ ) => [...match]),
+ [["su", "s"], ["cce", "cc"], ["ss", "ss"]],