-// ♓🌟 Piscēs ∷ string.test.js
-// ====================================================================
-//
-// Copyright © 2022–2023 Lady [@ Lady’s Computer].
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// License, v. 2.0. If a copy of the MPL was not distributed with this
-// file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+// SPDX-FileCopyrightText: 2022, 2023, 2025 Lady <https://www.ladys.computer/about/#lady>
+// SPDX-License-Identifier: MPL-2.0
+/**
+ * ⁌ ♓🧩 Piscēs ∷ string.test.js
+ *
+ * Copyright © 2022–2023, 2025 Lady [@ Ladys Computer].
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
+ */
import {
assert,
import {
asciiLowercase,
asciiUppercase,
+ canonicalNumericIndexString,
characters,
codepoints,
codeUnits,
getCodeUnit,
getFirstSubstringIndex,
getLastSubstringIndex,
+ isArrayIndexString,
+ isIntegerIndexString,
join,
Matcher,
rawString,
assert(new Matcher(/(?:)/u));
});
- it("[[Construct]] throws with a non·unicode regular expression first argument", () => {
+ it("[[Construct]] accepts a unicode sets regular expression first argument", () => {
+ assert(new Matcher(/(?:)/v));
+ });
+
+ it("[[Construct]] throws with a non·unicode·aware regular expression first argument", () => {
assertThrows(() => new 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);
assertStrictEquals(new Matcher(/(?:)/u).dotAll, false);
});
- describe(".length", () => {
+ describe("[[GetOwnProperty]].get.length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
- describe(".name", () => {
+ describe("[[GetOwnProperty]].get.name", () => {
it("[[Get]] returns the correct name", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
);
});
+ it("[[Construct]] throws an error", () => {
+ const matcher = new Matcher("");
+ assertThrows(() => new matcher.exec());
+ });
+
describe(".length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(Matcher.prototype.exec.length, 1);
assertStrictEquals(new Matcher(/(?:)/u).global, false);
});
- describe(".length", () => {
+ describe("[[GetOwnProperty]].get.length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
- describe(".name", () => {
+ describe("[[GetOwnProperty]].get.name", () => {
it("[[Get]] returns the correct name", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
assertStrictEquals(new Matcher(/(?:)/u).hasIndices, false);
});
- describe(".length", () => {
+ describe("[[GetOwnProperty]].get.length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
- describe(".name", () => {
+ describe("[[GetOwnProperty]].get.name", () => {
it("[[Get]] returns the correct name", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
assertStrictEquals(new Matcher(/(?:)/u).ignoreCase, false);
});
- describe(".length", () => {
+ describe("[[GetOwnProperty]].get.length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
- describe(".name", () => {
+ describe("[[GetOwnProperty]].get.name", () => {
it("[[Get]] returns the correct name", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
assertStrictEquals(new Matcher(/(?:)/u).multiline, false);
});
- describe(".length", () => {
+ describe("[[GetOwnProperty]].get.length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
- describe(".name", () => {
+ describe("[[GetOwnProperty]].get.name", () => {
it("[[Get]] returns the correct name", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
assertStrictEquals(new Matcher(/.*/su).source, ".*");
});
- describe(".length", () => {
+ describe("[[GetOwnProperty]].get.length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
- describe(".name", () => {
+ describe("[[GetOwnProperty]].get.name", () => {
it("[[Get]] returns the correct name", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
assertStrictEquals(new Matcher(/(?:)/u).sticky, false);
});
- describe(".length", () => {
+ describe("[[GetOwnProperty]].get.length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
- describe(".name", () => {
+ describe("[[GetOwnProperty]].get.name", () => {
it("[[Get]] returns the correct name", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
it("[[Call]] returns the string source", () => {
assertStrictEquals(new Matcher(/(?:)/u).toString(), "/(?:)/u");
});
+
+ it("[[Construct]] throws an error", () => {
+ const matcher = new Matcher("");
+ assertThrows(() => new matcher.toString());
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(Matcher.prototype.toString.length, 0);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Matcher.prototype.toString.name,
+ "toString",
+ );
+ });
+ });
});
describe("::unicode", () => {
assertStrictEquals(new Matcher(/(?:)/u).unicode, true);
});
- describe(".length", () => {
+ describe("[[GetOwnProperty]].get.length", () => {
it("[[Get]] returns the correct length", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
- describe(".name", () => {
+ describe("[[GetOwnProperty]].get.name", () => {
it("[[Get]] returns the correct name", () => {
assertStrictEquals(
Object.getOwnPropertyDescriptor(
});
});
+ describe("::unicodeSets", () => {
+ it("[[Get]] returns true when the unicode sets flag is present", () => {
+ assertStrictEquals(new Matcher(/(?:)/v).unicodeSets, true);
+ });
+
+ describe("[[GetOwnProperty]].get.length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "unicodeSets",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe("[[GetOwnProperty]].get.name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ Matcher.prototype,
+ "unicodeSets",
+ ).get.name,
+ "get unicodeSets",
+ );
+ });
+ });
+ });
+
describe("~", () => {
it("[[Call]] returns true for a complete match", () => {
assertStrictEquals(new Matcher("")(""), true);
false,
);
});
+
+ it("[[Construct]] throws an error", () => {
+ const matcher = new Matcher("");
+ assertThrows(() => new matcher(""));
+ });
});
describe("~lastIndex", () => {
});
});
+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(
});
});
+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");
"very success full",
/([sc]+)[ue]?/g,
(...$s) =>
- `${$s[0].length}`.repeat($s[1].length) +
- $s[0].substring($s[1].length),
+ `${$s[0].length}`.repeat($s[1].length)
+ + $s[0].substring($s[1].length),
),
"very 2u33e22 full",
);
"very success full",
/([sc]+)[ue]?/g,
(...$s) =>
- `${$s[0].length}`.repeat($s[1].length) +
- $s[0].substring($s[1].length),
+ `${$s[0].length}`.repeat($s[1].length)
+ + $s[0].substring($s[1].length),
),
"very 2u33e22 full",
);