X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/2989f964f0325a2d9c9294a8d3dab722313d5518..refs/heads/current:/string.test.js
diff --git a/string.test.js b/string.test.js
index 5d713f0..ee0e209 100644
--- a/string.test.js
+++ b/string.test.js
@@ -1,320 +1,1956 @@
// โ๐ Piscฤs โท string.test.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 .
import {
+ assert,
assertEquals,
+ assertSpyCalls,
assertStrictEquals,
+ assertThrows,
describe,
it,
+ spy,
} from "./dev-deps.js";
import {
asciiLowercase,
asciiUppercase,
+ canonicalNumericIndexString,
+ characters,
codepoints,
codeUnits,
getCharacter,
+ getCodepoint,
+ getCodeUnit,
+ getFirstSubstringIndex,
+ getLastSubstringIndex,
+ isArrayIndexString,
+ isIntegerIndexString,
join,
+ Matcher,
+ rawString,
scalarValues,
- scalarValueString,
- splitOnASCIIWhitespace,
+ splitOnAsciiWhitespace,
splitOnCommas,
- stripAndCollapseASCIIWhitespace,
- stripLeadingAndTrailingASCIIWhitespace,
+ stringCatenate,
+ stringEndsWith,
+ stringFromCodepoints,
+ stringFromCodeUnits,
+ stringIncludes,
+ stringMatch,
+ stringMatchAll,
+ stringNormalize,
+ stringPadEnd,
+ stringPadStart,
+ stringRepeat,
+ stringReplace,
+ stringReplaceAll,
+ stringSearch,
+ stringSlice,
+ stringSplit,
+ stringStartsWith,
+ stringValue,
+ stripAndCollapseAsciiWhitespace,
+ stripLeadingAndTrailingAsciiWhitespace,
+ substring,
+ toScalarValueString,
+ toString,
} from "./string.js";
+describe("Matcher", () => {
+ it("[[Call]] throws an error", () => {
+ assertThrows(() => Matcher(""));
+ });
+
+ it("[[Construct]] accepts a string first argument", () => {
+ assert(new Matcher(""));
+ });
+
+ it("[[Construct]] accepts a unicode regular expression first argument", () => {
+ assert(new Matcher(/(?:)/u));
+ });
+
+ it("[[Construct]] throws with a nonยทunicode regular expression first argument", () => {
+ assertThrows(() => new Matcher(/(?:)/));
+ });
+
+ it("[[Construct]] creates a callable object", () => {
+ assertStrictEquals(typeof new Matcher(""), "function");
+ });
+
+ it("[[Construct]] creates a new Matcher", () => {
+ assertStrictEquals(
+ Object.getPrototypeOf(new Matcher("")),
+ Matcher.prototype,
+ );
+ });
+
+ it("[[Construct]] creates an object which inherits from RegExp", () => {
+ assert(new Matcher("") instanceof RegExp);
+ });
+
+ it("[[Construct]] throws when provided with a noncallable, nonยทnull third argument", () => {
+ assertThrows(() => new Matcher("", undefined, "failure"));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(Matcher.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(Matcher.name, "Matcher");
+ });
+ });
+
+ describe("::constructor", () => {
+ it("[[Get]] returns the same constructor", () => {
+ assertStrictEquals(new Matcher(/(?:)/su).constructor, Matcher);
+ });
+ });
+
+ describe("::dotAll", () => {
+ it("[[Get]] returns true when the dotAll flag is present", () => {
+ assertStrictEquals(new Matcher(/(?:)/su).dotAll, true);
+ });
+
+ it("[[Get]] returns false when the dotAll flag is not present", () => {
+ assertStrictEquals(new Matcher(/(?:)/u).dotAll, false);
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "dotAll",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "dotAll",
+ ).get.name,
+ "get dotAll",
+ );
+ });
+ });
+ });
+
+ describe("::exec", () => {
+ it("[[Call]] returns the match object given a complete match", () => {
+ assertEquals(
+ [...new Matcher(/.(?(?:.(?=.))*)(.)?/u).exec("success")],
+ ["success", "ucces", "s"],
+ );
+ assertEquals(
+ [...new Matcher(
+ /.(?(?:.(?=.))*)(.)?/u,
+ undefined,
+ ($) => $ === "success",
+ ).exec("success")],
+ ["success", "ucces", "s"],
+ );
+ });
+
+ it("[[Call]] calls the constraint if the match succeeds", () => {
+ const constraint = spy((_) => true);
+ const matcher = new Matcher("(.).*", undefined, constraint);
+ const result = matcher.exec({
+ toString() {
+ return "etaoin";
+ },
+ });
+ assertEquals([...result], ["etaoin", "e"]);
+ assertSpyCalls(constraint, 1);
+ assertStrictEquals(constraint.calls[0].args[0], "etaoin");
+ assertEquals([...constraint.calls[0].args[1]], ["etaoin", "e"]);
+ assertStrictEquals(constraint.calls[0].args[2], matcher);
+ assertStrictEquals(constraint.calls[0].self, undefined);
+ });
+
+ it("[[Call]] does not call the constraint if the match fails", () => {
+ const constraint = spy((_) => true);
+ const matcher = new Matcher("", undefined, constraint);
+ matcher.exec("failure");
+ assertSpyCalls(constraint, 0);
+ });
+
+ it("[[Call]] returns null given a partial match", () => {
+ assertStrictEquals(new Matcher("").exec("failure"), null);
+ });
+
+ it("[[Call]] returns null if the constraint fails", () => {
+ assertStrictEquals(
+ new Matcher(".*", undefined, () => false).exec(""),
+ null,
+ );
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(Matcher.prototype.exec.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(Matcher.prototype.exec.name, "exec");
+ });
+ });
+ });
+
+ describe("::global", () => {
+ it("[[Get]] returns true when the global flag is present", () => {
+ assertStrictEquals(new Matcher(/(?:)/gu).global, true);
+ });
+
+ it("[[Get]] returns false when the global flag is not present", () => {
+ assertStrictEquals(new Matcher(/(?:)/u).global, false);
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "global",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "global",
+ ).get.name,
+ "get global",
+ );
+ });
+ });
+ });
+
+ describe("::hasIndices", () => {
+ it("[[Get]] returns true when the hasIndices flag is present", () => {
+ assertStrictEquals(new Matcher(/(?:)/du).hasIndices, true);
+ });
+
+ it("[[Get]] returns false when the hasIndices flag is not present", () => {
+ assertStrictEquals(new Matcher(/(?:)/u).hasIndices, false);
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "hasIndices",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "hasIndices",
+ ).get.name,
+ "get hasIndices",
+ );
+ });
+ });
+ });
+
+ describe("::ignoreCase", () => {
+ it("[[Get]] returns true when the ignoreCase flag is present", () => {
+ assertStrictEquals(new Matcher(/(?:)/iu).ignoreCase, true);
+ });
+
+ it("[[Get]] returns false when the ignoreCase flag is not present", () => {
+ assertStrictEquals(new Matcher(/(?:)/u).ignoreCase, false);
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "ignoreCase",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "ignoreCase",
+ ).get.name,
+ "get ignoreCase",
+ );
+ });
+ });
+ });
+
+ describe("::multiline", () => {
+ it("[[Get]] returns true when the multiline flag is present", () => {
+ assertStrictEquals(new Matcher(/(?:)/mu).multiline, true);
+ });
+
+ it("[[Get]] returns false when the multiline flag is not present", () => {
+ assertStrictEquals(new Matcher(/(?:)/u).multiline, false);
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "multiline",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "multiline",
+ ).get.name,
+ "get multiline",
+ );
+ });
+ });
+ });
+
+ describe("::source", () => {
+ it("[[Get]] returns the RegExp source", () => {
+ assertStrictEquals(new Matcher("").source, "(?:)");
+ assertStrictEquals(new Matcher(/.*/su).source, ".*");
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "source",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "source",
+ ).get.name,
+ "get source",
+ );
+ });
+ });
+ });
+
+ describe("::sticky", () => {
+ it("[[Get]] returns true when the sticky flag is present", () => {
+ assertStrictEquals(new Matcher(/(?:)/uy).sticky, true);
+ });
+
+ it("[[Get]] returns false when the sticky flag is not present", () => {
+ assertStrictEquals(new Matcher(/(?:)/u).sticky, false);
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "sticky",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "sticky",
+ ).get.name,
+ "get sticky",
+ );
+ });
+ });
+ });
+
+ describe("::toString", () => {
+ it("[[Call]] returns the string source", () => {
+ assertStrictEquals(new Matcher(/(?:)/u).toString(), "/(?:)/u");
+ });
+ });
+
+ describe("::unicode", () => {
+ it("[[Get]] returns true when the unicode flag is present", () => {
+ assertStrictEquals(new Matcher(/(?:)/u).unicode, true);
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "unicode",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "unicode",
+ ).get.name,
+ "get unicode",
+ );
+ });
+ });
+ });
+
+ describe("~", () => {
+ it("[[Call]] returns true for a complete match", () => {
+ assertStrictEquals(new Matcher("")(""), true);
+ assertStrictEquals(new Matcher(/.*/su)("success\nyay"), true);
+ assertStrictEquals(
+ new Matcher(/.*/su, undefined, ($) => $ === "success")(
+ "success",
+ ),
+ true,
+ );
+ });
+
+ it("[[Call]] calls the constraint if the match succeeds", () => {
+ const constraint = spy((_) => true);
+ const matcher = new Matcher("(.).*", undefined, constraint);
+ matcher("etaoin");
+ assertSpyCalls(constraint, 1);
+ assertStrictEquals(constraint.calls[0].args[0], "etaoin");
+ assertEquals([...constraint.calls[0].args[1]], ["etaoin", "e"]);
+ assertStrictEquals(constraint.calls[0].args[2], matcher);
+ assertStrictEquals(constraint.calls[0].self, undefined);
+ });
+
+ it("[[Call]] does not call the constraint if the match fails", () => {
+ const constraint = spy((_) => true);
+ const matcher = new Matcher("", undefined, constraint);
+ matcher("failure");
+ assertSpyCalls(constraint, 0);
+ });
+
+ it("[[Call]] returns false for a partial match", () => {
+ assertStrictEquals(new Matcher("")("failure"), false);
+ assertStrictEquals(new Matcher(/.*/u)("failure\nno"), false);
+ });
+
+ it("[[Call]] returns false if the constraint fails", () => {
+ assertStrictEquals(
+ new Matcher(".*", undefined, () => false)(""),
+ false,
+ );
+ });
+ });
+
+ describe("~lastIndex", () => {
+ it("[[Get]] returns zero", () => {
+ assertStrictEquals(new Matcher("").lastIndex, 0);
+ });
+
+ it("[[Set]] fails", () => {
+ assertThrows(() => (new Matcher("").lastIndex = 1));
+ });
+ });
+
+ describe("~length", () => {
+ it("[[Get]] returns one", () => {
+ assertStrictEquals(new Matcher("").length, 1);
+ });
+ });
+
+ describe("~name", () => {
+ it("[[Get]] wraps the stringified regular expression if no name was provided", () => {
+ assertStrictEquals(new Matcher("").name, "Matcher(/(?:)/u)");
+ assertStrictEquals(
+ new Matcher(/.*/gsu).name,
+ "Matcher(/.*/gsu)",
+ );
+ });
+
+ it("[[Get]] uses the provided name if one was provided", () => {
+ assertStrictEquals(new Matcher("", "success").name, "success");
+ });
+ });
+});
+
describe("asciiLowercase", () => {
it("[[Call]] lowercases (just) AยทSยทCยทIยทI letters", () => {
assertStrictEquals(asciiLowercase("aBลฟรss Ftษษร"), "abลฟรss ftษษร");
});
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new asciiLowercase(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(asciiLowercase.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(asciiLowercase.name, "asciiLowercase");
+ });
+ });
+});
+
+describe("asciiUppercase", () => {
+ it("[[Call]] uppercases (just) AยทSยทCยทIยทI letters", () => {
+ assertStrictEquals(asciiUppercase("aBลฟรss Ftษษร"), "ABลฟรSS FTษษร");
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new asciiUppercase(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(asciiUppercase.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(asciiUppercase.name, "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(
+ typeof characters("")[Symbol.iterator],
+ "function",
+ );
+ });
+
+ it("[[Call]] returns an iterator", () => {
+ assertStrictEquals(typeof characters("").next, "function");
+ });
+
+ it("[[Call]] returns a string character iterator", () => {
+ assertStrictEquals(
+ characters("")[Symbol.toStringTag],
+ "String Character Iterator",
+ );
+ });
+
+ it("[[Call]] iterates over the characters", () => {
+ assertEquals([
+ ...characters("Ii๐\uDFFF\uDD96\uD83C\uD800๐โบ"),
+ ], [
+ "I",
+ "i",
+ "๐",
+ "\uDFFF",
+ "\uDD96",
+ "\uD83C",
+ "\uD800",
+ "๐",
+ "โบ",
+ ]);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new characters(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(characters.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(characters.name, "characters");
+ });
+ });
+});
+
+describe("codeUnits", () => {
+ it("[[Call]] returns an iterable", () => {
+ assertStrictEquals(
+ typeof codeUnits("")[Symbol.iterator],
+ "function",
+ );
+ });
+
+ it("[[Call]] returns an iterator", () => {
+ assertStrictEquals(typeof codeUnits("").next, "function");
+ });
+
+ it("[[Call]] returns a string code unit iterator", () => {
+ assertStrictEquals(
+ codeUnits("")[Symbol.toStringTag],
+ "String Code Unit Iterator",
+ );
+ });
+
+ it("[[Call]] iterates over the code units", () => {
+ assertEquals([
+ ...codeUnits("Ii๐\uDFFF\uDD96\uD83C\uD800๐โบ"),
+ ], [
+ 0x49,
+ 0x69,
+ 0xD83C,
+ 0xDF99,
+ 0xDFFF,
+ 0xDD96,
+ 0xD83C,
+ 0xD800,
+ 0xD83C,
+ 0xDD97,
+ 0x263A,
+ ]);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new codeUnits(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(codeUnits.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(codeUnits.name, "codeUnits");
+ });
+ });
+});
+
+describe("codepoints", () => {
+ it("[[Call]] returns an iterable", () => {
+ assertStrictEquals(
+ typeof codepoints("")[Symbol.iterator],
+ "function",
+ );
+ });
+
+ it("[[Call]] returns an iterator", () => {
+ assertStrictEquals(typeof codepoints("").next, "function");
+ });
+
+ it("[[Call]] returns a string codepoint iterator", () => {
+ assertStrictEquals(
+ codepoints("")[Symbol.toStringTag],
+ "String Codepoint Iterator",
+ );
+ });
+
+ it("[[Call]] iterates over the codepoints", () => {
+ assertEquals([
+ ...codepoints("Ii๐\uDFFF\uDD96\uD83C\uD800๐โบ"),
+ ], [
+ 0x49,
+ 0x69,
+ 0x1F399,
+ 0xDFFF,
+ 0xDD96,
+ 0xD83C,
+ 0xD800,
+ 0x1F197,
+ 0x263A,
+ ]);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new codepoints(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(codepoints.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(codepoints.name, "codepoints");
+ });
+ });
+});
+
+describe("getCharacter", () => {
+ it("[[Call]] returns the character at the provided position", () => {
+ assertStrictEquals(getCharacter("Ii๐๐โบ", 4), "๐");
+ });
+
+ it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
+ assertStrictEquals(getCharacter("Ii๐๐โบ", 5), "\uDD97");
+ });
+
+ it("[[Call]] returns undefined for an outโofโbounds index", () => {
+ assertStrictEquals(getCharacter("Ii๐๐โบ", -1), undefined);
+ assertStrictEquals(getCharacter("Ii๐๐โบ", 7), undefined);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new getCharacter("a", 0));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(getCharacter.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(getCharacter.name, "getCharacter");
+ });
+ });
});
-describe("asciiUppercase", () => {
- it("[[Call]] uppercases (just) AยทSยทCยทIยทI letters", () => {
- assertStrictEquals(asciiUppercase("aBลฟรss Ftษษร"), "ABลฟรSS FTษษร");
+describe("getCodeUnit", () => {
+ it("[[Call]] returns the code unit at the provided position", () => {
+ assertStrictEquals(getCodeUnit("Ii๐๐โบ", 4), 0xD83C);
+ });
+
+ it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
+ assertStrictEquals(getCodeUnit("Ii๐๐โบ", 5), 0xDD97);
+ });
+
+ it("[[Call]] returns undefined for an outโofโbounds index", () => {
+ assertStrictEquals(getCodeUnit("Ii๐๐โบ", -1), undefined);
+ assertStrictEquals(getCodeUnit("Ii๐๐โบ", 7), undefined);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new getCodeUnit("a", 0));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(getCodeUnit.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(getCodeUnit.name, "getCodeUnit");
+ });
+ });
+});
+
+describe("getCodepoint", () => {
+ it("[[Call]] returns the character at the provided position", () => {
+ assertStrictEquals(getCodepoint("Ii๐๐โบ", 4), 0x1F197);
+ });
+
+ it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
+ assertStrictEquals(getCodepoint("Ii๐๐โบ", 5), 0xDD97);
+ });
+
+ it("[[Call]] returns undefined for an outโofโbounds index", () => {
+ assertStrictEquals(getCodepoint("Ii๐๐โบ", -1), undefined);
+ assertStrictEquals(getCodepoint("Ii๐๐โบ", 7), undefined);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new getCodepoint("a", 0));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(getCodepoint.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(getCodepoint.name, "getCodepoint");
+ });
+ });
+});
+
+describe("getFirstSubstringIndex", () => {
+ it("[[Call]] returns the index of the first match", () => {
+ assertStrictEquals(getFirstSubstringIndex("Ii๐๐โบ๐", "๐"), 4);
+ });
+
+ it("[[Call]] returns โ1 if no match is found", () => {
+ assertStrictEquals(getFirstSubstringIndex("Ii๐๐โบ๐", "๐๐"), -1);
+ });
+
+ it("[[Call]] returns 0 when provided with an empty string", () => {
+ assertStrictEquals(getFirstSubstringIndex("Ii๐๐โบ๐", ""), 0);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new getFirstSubstringIndex("", ""));
+ });
+
+ 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"]],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringMatchAll("", /(?:)/g));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringMatchAll.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringMatchAll.name, "stringMatchAll");
+ });
+ });
+});
+
+describe("stringNormalize", () => {
+ it("[[Call]] normalizes the string properly", () => {
+ assertStrictEquals(stringNormalize("แบ", "NFC"), "\u1E9B");
+ assertStrictEquals(stringNormalize("แบ", "NFD"), "\u017F\u0307");
+ assertStrictEquals(stringNormalize("แบ", "NFKC"), "\u1E61");
+ assertStrictEquals(stringNormalize("แบ", "NFKD"), "\u0073\u0307");
+ });
+
+ it("[[Call]] assumes NFC", () => {
+ assertStrictEquals(stringNormalize("\u017F\u0307"), "\u1E9B");
+ });
+
+ it("[[Call]] throws with an invalid form", () => {
+ assertThrows(() => stringNormalize("", "NFB"));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringNormalize("", "NFC"));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringNormalize.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringNormalize.name, "stringNormalize");
+ });
});
});
-describe("codeUnits", () => {
- it("[[Call]] returns an iterable", () => {
- assertStrictEquals(
- typeof codeUnits("")[Symbol.iterator],
- "function",
- );
+describe("stringPadEnd", () => {
+ it("[[Call]] pads the end of the string", () => {
+ assertStrictEquals(stringPadEnd("xx", 3), "xx ");
+ assertStrictEquals(stringPadEnd("xx", 3, "o"), "xxo");
+ assertStrictEquals(stringPadEnd("", 3, "xo"), "xox");
+ assertStrictEquals(stringPadEnd("xx", 3, ""), "xx");
});
- it("[[Call]] returns an iterator", () => {
- assertStrictEquals(typeof codeUnits("").next, "function");
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringPadEnd("", 1));
});
- it("[[Call]] returns a string code value iterator", () => {
- assertStrictEquals(
- codeUnits("")[Symbol.toStringTag],
- "String Code Value Iterator",
- );
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringPadEnd.length, 2);
+ });
});
- it("[[Call]] iterates over the code units", () => {
- assertEquals([
- ...codeUnits("Ii๐\uDFFF\uDD96\uD83C\uD800๐โบ"),
- ], [
- 0x49,
- 0x69,
- 0xD83C,
- 0xDF99,
- 0xDFFF,
- 0xDD96,
- 0xD83C,
- 0xD800,
- 0xD83C,
- 0xDD97,
- 0x263A,
- ]);
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringPadEnd.name, "stringPadEnd");
+ });
});
});
-describe("codepoints", () => {
- it("[[Call]] returns an iterable", () => {
- assertStrictEquals(
- typeof codepoints("")[Symbol.iterator],
- "function",
- );
+describe("stringPadStart", () => {
+ it("[[Call]] pads the start of the string", () => {
+ assertStrictEquals(stringPadStart("xx", 3), " xx");
+ assertStrictEquals(stringPadStart("xx", 3, "o"), "oxx");
+ assertStrictEquals(stringPadStart("", 3, "xo"), "xox");
+ assertStrictEquals(stringPadStart("xx", 3, ""), "xx");
});
- it("[[Call]] returns an iterator", () => {
- assertStrictEquals(typeof codepoints("").next, "function");
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringPadStart("", 1));
});
- it("[[Call]] returns a string code value iterator", () => {
- assertStrictEquals(
- codepoints("")[Symbol.toStringTag],
- "String Code Value Iterator",
- );
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringPadStart.length, 2);
+ });
});
- it("[[Call]] iterates over the codepoints", () => {
- assertEquals([
- ...codepoints("Ii๐\uDFFF\uDD96\uD83C\uD800๐โบ"),
- ], [
- 0x49,
- 0x69,
- 0x1F399,
- 0xDFFF,
- 0xDD96,
- 0xD83C,
- 0xD800,
- 0x1F197,
- 0x263A,
- ]);
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringPadStart.name, "stringPadStart");
+ });
});
});
-describe("getCharacter", () => {
- it("[[Call]] returns the character at the provided position", () => {
- assertStrictEquals(getCharacter("Ii๐๐โบ", 4), "๐");
+describe("stringRepeat", () => {
+ it("[[Call]] repeats the string", () => {
+ assertStrictEquals(stringRepeat("xx", 3), "xxxxxx");
+ assertStrictEquals(stringRepeat("", 3), "");
+ assertStrictEquals(stringRepeat("xx", 0), "");
});
- it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
- assertStrictEquals(getCharacter("Ii๐๐โบ", 5), "\uDD97");
+ it("[[Call]] throws for negative repititions", () => {
+ assertThrows(() => stringRepeat("", -1));
});
- it("[[Call]] returns undefined for an outโofโbounds index", () => {
- assertStrictEquals(getCharacter("Ii๐๐โบ", -1), void {});
- assertStrictEquals(getCharacter("Ii๐๐โบ", 7), void {});
+ it("[[Call]] throws for infinite repititions", () => {
+ assertThrows(() => stringRepeat("", Infinity));
});
-});
-describe("join", () => {
- it("[[Call]] joins the provided iterator with the provided separartor", () => {
- assertStrictEquals(join([1, 2, 3, 4].values(), "โ"), "1โ2โ3โ4");
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringRepeat("", 1));
});
- it('[[Call]] uses "," if no separator is provided', () => {
- assertStrictEquals(join([1, 2, 3, 4].values()), "1,2,3,4");
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringRepeat.length, 2);
+ });
});
- it("[[Call]] uses the empty sting for nullish values", () => {
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringRepeat.name, "stringRepeat");
+ });
+ });
+});
+
+describe("stringReplace", () => {
+ it("[[Call]] does the replacement akin to String::replace", () => {
assertStrictEquals(
- join([null, , null, undefined].values(), "โ"),
- "โโโ",
+ stringReplace("itโs a failure", "failure", "success"),
+ "itโs a success",
+ );
+ assertStrictEquals(
+ stringReplace(
+ "very success full",
+ /([sc]+)[ue]?/,
+ ($) => $.length,
+ ),
+ "very 2ccess full",
);
+ assertStrictEquals(
+ stringReplace(
+ "very success full",
+ /([sc]+)[ue]?/g,
+ (...$s) =>
+ `${$s[0].length}`.repeat($s[1].length) +
+ $s[0].substring($s[1].length),
+ ),
+ "very 2u33e22 full",
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringReplace("", /(?:)/, ""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringReplace.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringReplace.name, "stringReplace");
+ });
});
});
-describe("scalarValueString", () => {
- it("[[Call]] replaces invalid values", () => {
+describe("stringReplaceAll", () => {
+ it("[[Call]] does the match akin to String::replaceAll", () => {
assertStrictEquals(
- scalarValueString("Ii๐\uDFFF\uDD96\uD83C\uD800๐โบ"),
- "Ii๐\uFFFD\uFFFD\uFFFD\uFFFD๐โบ",
+ stringReplaceAll("itโs a failure failure", "failure", "success"),
+ "itโs a success success",
+ );
+ assertStrictEquals(
+ stringReplaceAll(
+ "very success full",
+ /([sc]+)[ue]?/g,
+ (...$s) =>
+ `${$s[0].length}`.repeat($s[1].length) +
+ $s[0].substring($s[1].length),
+ ),
+ "very 2u33e22 full",
);
});
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringReplaceAll("", /(?:)/g));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringReplaceAll.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringReplaceAll.name, "stringReplaceAll");
+ });
+ });
});
-describe("scalarValues", () => {
- it("[[Call]] returns an iterable", () => {
+describe("stringSearch", () => {
+ it("[[Call]] does the search akin to String::search", () => {
assertStrictEquals(
- typeof scalarValues("")[Symbol.iterator],
- "function",
+ stringSearch("very success full", /([sc]+)[ue]?/),
+ 5,
+ );
+ assertStrictEquals(
+ stringSearch("very fail full", /([sc]+)[ue]?/),
+ -1,
);
});
- it("[[Call]] returns an iterator", () => {
- assertStrictEquals(typeof scalarValues("").next, "function");
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringSearch("", /(?:)/));
});
- it("[[Call]] returns a string code value iterator", () => {
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringSearch.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringSearch.name, "stringSearch");
+ });
+ });
+});
+
+describe("stringSlice", () => {
+ it("[[Call]] slices the string akin to String::search", () => {
assertStrictEquals(
- scalarValues("")[Symbol.toStringTag],
- "String Code Value Iterator",
+ stringSlice("very success full", 5, 12),
+ "success",
+ );
+ assertStrictEquals(
+ stringSlice("very success full", -12, -5),
+ "success",
);
});
- 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 stringSlice("", 0, 0));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringSlice.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringSlice.name, "stringSlice");
+ });
});
});
-describe("splitOnASCIIWhitespace", () => {
- it("[[Call]] splits on sequences of spaces", () => {
- assertEquals(
- splitOnASCIIWhitespace("๐
ฐ๏ธ ๐
ฑ๏ธ ๐ ๐
พ๏ธ"),
- ["๐
ฐ๏ธ", "๐
ฑ๏ธ", "๐", "๐
พ๏ธ"],
- );
+describe("stringSplit", () => {
+ it("[[Call]] splits the string akin to String::split", () => {
+ assertEquals(stringSplit("success", ""), [
+ "s",
+ "u",
+ "c",
+ "c",
+ "e",
+ "s",
+ "s",
+ ]);
+ assertEquals(stringSplit("success", /(?<=[aeiou])(?=[^aeiou])/), [
+ "su",
+ "cce",
+ "ss",
+ ]);
+ assertEquals(stringSplit("success", "failure"), ["success"]);
});
- it("[[Call]] splits on sequences of tabs", () => {
- assertEquals(
- splitOnASCIIWhitespace("๐
ฐ๏ธ\t\t\t๐
ฑ๏ธ\t๐\t\t๐
พ๏ธ"),
- ["๐
ฐ๏ธ", "๐
ฑ๏ธ", "๐", "๐
พ๏ธ"],
- );
+ it("[[Call]] recognizes a limit", () => {
+ assertEquals(stringSplit("success", "", 4), ["s", "u", "c", "c"]);
});
- it("[[Call]] splits on sequences of carriage returns", () => {
- assertEquals(
- splitOnASCIIWhitespace("๐
ฐ๏ธ\r\r\r๐
ฑ๏ธ\r๐\r\r๐
พ๏ธ"),
- ["๐
ฐ๏ธ", "๐
ฑ๏ธ", "๐", "๐
พ๏ธ"],
- );
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringSplit("", ""));
});
- it("[[Call]] splits on sequences of newlines", () => {
- assertEquals(
- splitOnASCIIWhitespace("๐
ฐ๏ธ\r\r\r๐
ฑ๏ธ\r๐\r\r๐
พ๏ธ"),
- ["๐
ฐ๏ธ", "๐
ฑ๏ธ", "๐", "๐
พ๏ธ"],
- );
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringSplit.length, 3);
+ });
});
- it("[[Call]] splits on sequences of form feeds", () => {
- assertEquals(
- splitOnASCIIWhitespace("๐
ฐ๏ธ\f\f\f๐
ฑ๏ธ\f๐\f\f๐
พ๏ธ"),
- ["๐
ฐ๏ธ", "๐
ฑ๏ธ", "๐", "๐
พ๏ธ"],
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringSplit.name, "stringSplit");
+ });
+ });
+});
+
+describe("stringStartsWith", () => {
+ it("[[Call]] returns whether the string starts with the thing", () => {
+ assertStrictEquals(
+ stringStartsWith("success is had", "success "),
+ true,
+ );
+ assertStrictEquals(
+ stringStartsWith("no success is had", "success "),
+ false,
);
});
- it("[[Call]] splits on mixed whitespace", () => {
- assertEquals(
- splitOnASCIIWhitespace("๐
ฐ๏ธ\f \t\n๐
ฑ๏ธ\r\n\r๐\n\f๐
พ๏ธ"),
- ["๐
ฐ๏ธ", "๐
ฑ๏ธ", "๐", "๐
พ๏ธ"],
+ it("[[Call]] accepts an offset", () => {
+ assertStrictEquals(
+ stringStartsWith("much success is had", "success ", 5),
+ true,
);
});
- it("[[Call]] returns an array of just the empty string for the empty string", () => {
- assertEquals(splitOnASCIIWhitespace(""), [""]);
+ it("[[Call]] returns true for an empty string test", () => {
+ assertStrictEquals(stringEndsWith("", ""), true);
});
- it("[[Call]] returns a single token if there are no spaces", () => {
- assertEquals(splitOnASCIIWhitespace("abcd"), ["abcd"]);
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringStartsWith("", ""));
});
- 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"],
- );
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringStartsWith.length, 2);
+ });
});
- it("[[Call]] trims leading and trailing whitespace", () => {
- assertEquals(
- splitOnASCIIWhitespace(
- "\f\r\n\r\n \n\t๐
ฐ๏ธ\f \t\n๐
ฑ๏ธ\r๐\n\f๐
พ๏ธ\n\f",
- ),
- ["๐
ฐ๏ธ", "๐
ฑ๏ธ", "๐", "๐
พ๏ธ"],
- );
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringStartsWith.name, "stringStartsWith");
+ });
});
});
-describe("splitOnCommas", () => {
- it("[[Call]] splits on commas", () => {
- assertEquals(
- splitOnCommas("๐
ฐ๏ธ,๐
ฑ๏ธ,๐,๐
พ๏ธ"),
- ["๐
ฐ๏ธ", "๐
ฑ๏ธ", "๐", "๐
พ๏ธ"],
- );
+describe("stringStartsWith", () => {
+ it("[[Call]] returns the string value of a string literal", () => {
+ assertStrictEquals(stringValue("success"), "success");
});
- it("[[Call]] returns an array of just the empty string for the empty string", () => {
- assertEquals(splitOnCommas(""), [""]);
+ it("[[Call]] returns the string value of a string object", () => {
+ const string = new String("success");
+ Object.defineProperties(string, {
+ toString: { value: () => "failure" },
+ valueOf: { value: () => "failure" },
+ });
+ assertStrictEquals(stringValue(string), "success");
});
- it("[[Call]] returns a single token if there are no commas", () => {
- assertEquals(splitOnCommas("abcd"), ["abcd"]);
+ it("[[Call]] throws for nonโstrings", () => {
+ assertThrows(() => stringValue(Object.create(String.prototype)));
});
- it("[[Call]] splits into empty strings if there are only commas", () => {
- assertEquals(splitOnCommas(",,,"), ["", "", "", ""]);
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stringValue(""));
});
- 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"),
- ["", "", "", ""],
- );
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stringValue.length, 1);
+ });
});
- 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"),
- ["", "", "", ""],
- );
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(stringValue.name, "stringValue");
+ });
});
});
-describe("stripAndCollapseASCIIWhitespace", () => {
+describe("stripAndCollapseAsciiWhitespace", () => {
it("[[Call]] collapses mixed inner whitespace", () => {
assertEquals(
- stripAndCollapseASCIIWhitespace("๐
ฐ๏ธ\f \t\n๐
ฑ๏ธ\r\n\r๐\n\f๐
พ๏ธ"),
+ stripAndCollapseAsciiWhitespace("๐
ฐ๏ธ\f \t\n๐
ฑ๏ธ\r\n\r๐\n\f๐
พ๏ธ"),
"๐
ฐ๏ธ ๐
ฑ๏ธ ๐ ๐
พ๏ธ",
);
});
it("[[Call]] trims leading and trailing whitespace", () => {
assertStrictEquals(
- stripAndCollapseASCIIWhitespace(
+ stripAndCollapseAsciiWhitespace(
"\f\r\n\r\n \n\t\f ๐
ฐ๏ธ\f \t\n๐
ฑ๏ธ\r\n\r๐\n\f๐
พ๏ธ\n\f",
),
"๐
ฐ๏ธ ๐
ฑ๏ธ ๐ ๐
พ๏ธ",
@@ -323,23 +1959,42 @@ describe("stripAndCollapseASCIIWhitespace", () => {
it("[[Call]] returns the empty string for strings of whitespace", () => {
assertStrictEquals(
- stripAndCollapseASCIIWhitespace("\f\r\n\r\n \n\t\f \n\f"),
+ stripAndCollapseAsciiWhitespace("\f\r\n\r\n \n\t\f \n\f"),
"",
);
});
it("[[Call]] does not collapse other kinds of whitespace", () => {
assertEquals(
- stripAndCollapseASCIIWhitespace("a\u202F\u205F\xa0\v\0\bb"),
+ stripAndCollapseAsciiWhitespace("a\u202F\u205F\xa0\v\0\bb"),
"a\u202F\u205F\xa0\v\0\bb",
);
});
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stripAndCollapseAsciiWhitespace(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(stripAndCollapseAsciiWhitespace.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ stripAndCollapseAsciiWhitespace.name,
+ "stripAndCollapseAsciiWhitespace",
+ );
+ });
+ });
});
-describe("stripLeadingAndTrailingASCIIWhitespace", () => {
+describe("stripLeadingAndTrailingAsciiWhitespace", () => {
it("[[Call]] trims leading and trailing whitespace", () => {
assertStrictEquals(
- stripLeadingAndTrailingASCIIWhitespace(
+ stripLeadingAndTrailingAsciiWhitespace(
"\f\r\n\r\n \n\t\f ๐
ฐ๏ธ๐
ฑ๏ธ๐๐
พ๏ธ\n\f",
),
"๐
ฐ๏ธ๐
ฑ๏ธ๐๐
พ๏ธ",
@@ -348,14 +2003,14 @@ describe("stripLeadingAndTrailingASCIIWhitespace", () => {
it("[[Call]] returns the empty string for strings of whitespace", () => {
assertStrictEquals(
- stripLeadingAndTrailingASCIIWhitespace("\f\r\n\r\n \n\t\f \n\f"),
+ stripLeadingAndTrailingAsciiWhitespace("\f\r\n\r\n \n\t\f \n\f"),
"",
);
});
it("[[Call]] does not trim other kinds of whitespace", () => {
assertEquals(
- stripLeadingAndTrailingASCIIWhitespace(
+ stripLeadingAndTrailingAsciiWhitespace(
"\v\u202F\u205Fx\0\b\xa0",
),
"\v\u202F\u205Fx\0\b\xa0",
@@ -364,8 +2019,120 @@ describe("stripLeadingAndTrailingASCIIWhitespace", () => {
it("[[Call]] does not adjust inner whitespace", () => {
assertEquals(
- stripLeadingAndTrailingASCIIWhitespace("a b"),
+ stripLeadingAndTrailingAsciiWhitespace("a b"),
"a b",
);
});
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new stripLeadingAndTrailingAsciiWhitespace(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ stripLeadingAndTrailingAsciiWhitespace.length,
+ 1,
+ );
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ stripLeadingAndTrailingAsciiWhitespace.name,
+ "stripLeadingAndTrailingAsciiWhitespace",
+ );
+ });
+ });
+});
+
+describe("substring", () => {
+ it("[[Call]] returns the substring", () => {
+ assertStrictEquals(
+ substring("success", 0),
+ "success",
+ );
+ assertStrictEquals(
+ substring("very success full", 5, 12),
+ "success",
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new substring("", 0));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(substring.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(substring.name, "substring");
+ });
+ });
+});
+
+describe("toScalarValueString", () => {
+ it("[[Call]] replaces invalid values", () => {
+ assertStrictEquals(
+ toScalarValueString("Ii๐\uDFFF\uDD96\uD83C\uD800๐โบ"),
+ "Ii๐\uFFFD\uFFFD\uFFFD\uFFFD๐โบ",
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new toScalarValueString(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(toScalarValueString.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ toScalarValueString.name,
+ "toScalarValueString",
+ );
+ });
+ });
+});
+
+describe("toString", () => {
+ it("[[Call]] converts to a string", () => {
+ assertStrictEquals(
+ toString({
+ toString() {
+ return "success";
+ },
+ }),
+ "success",
+ );
+ });
+
+ it("[[Call]] throws when provided a symbol", () => {
+ assertThrows(() => toString(Symbol()));
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new toString(""));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(toString.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(toString.name, "toString");
+ });
+ });
});