]> Lady’s Gitweb - Pisces/blob - string.test.js
Support unicode sets in Matchers
[Pisces] / string.test.js
1 // SPDX-FileCopyrightText: 2022, 2023, 2025 Lady <https://www.ladys.computer/about/#lady>
2 // SPDX-License-Identifier: MPL-2.0
3 /**
4 * ⁌ ♓🧩 Piscēs ∷ string.test.js
5 *
6 * Copyright © 2022–2023, 2025 Lady [@ Ladys Computer].
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
11 */
12
13 import {
14 assert,
15 assertEquals,
16 assertSpyCalls,
17 assertStrictEquals,
18 assertThrows,
19 describe,
20 it,
21 spy,
22 } from "./dev-deps.js";
23 import {
24 asciiLowercase,
25 asciiUppercase,
26 canonicalNumericIndexString,
27 characters,
28 codepoints,
29 codeUnits,
30 getCharacter,
31 getCodepoint,
32 getCodeUnit,
33 getFirstSubstringIndex,
34 getLastSubstringIndex,
35 isArrayIndexString,
36 isIntegerIndexString,
37 join,
38 Matcher,
39 rawString,
40 scalarValues,
41 splitOnAsciiWhitespace,
42 splitOnCommas,
43 stringCatenate,
44 stringEndsWith,
45 stringFromCodepoints,
46 stringFromCodeUnits,
47 stringIncludes,
48 stringMatch,
49 stringMatchAll,
50 stringNormalize,
51 stringPadEnd,
52 stringPadStart,
53 stringRepeat,
54 stringReplace,
55 stringReplaceAll,
56 stringSearch,
57 stringSlice,
58 stringSplit,
59 stringStartsWith,
60 stringValue,
61 stripAndCollapseAsciiWhitespace,
62 stripLeadingAndTrailingAsciiWhitespace,
63 substring,
64 toScalarValueString,
65 toString,
66 } from "./string.js";
67
68 describe("Matcher", () => {
69 it("[[Call]] throws an error", () => {
70 assertThrows(() => Matcher(""));
71 });
72
73 it("[[Construct]] accepts a string first argument", () => {
74 assert(new Matcher(""));
75 });
76
77 it("[[Construct]] accepts a unicode regular expression first argument", () => {
78 assert(new Matcher(/(?:)/u));
79 });
80
81 it("[[Construct]] accepts a unicode sets regular expression first argument", () => {
82 assert(new Matcher(/(?:)/v));
83 });
84
85 it("[[Construct]] throws with a non·unicode·aware regular expression first argument", () => {
86 assertThrows(() => new Matcher(/(?:)/));
87 });
88
89 it("[[Construct]] creates a callable object", () => {
90 assertStrictEquals(typeof new Matcher(""), "function");
91 });
92
93 it("[[Construct]] creates a new Matcher", () => {
94 assertStrictEquals(
95 Object.getPrototypeOf(new Matcher("")),
96 Matcher.prototype,
97 );
98 });
99
100 it("[[Construct]] creates an object which inherits from RegExp", () => {
101 assert(new Matcher("") instanceof RegExp);
102 });
103
104 it("[[Construct]] throws when provided with a noncallable, non·null third argument", () => {
105 assertThrows(() => new Matcher("", undefined, "failure"));
106 });
107
108 describe(".length", () => {
109 it("[[Get]] returns the correct length", () => {
110 assertStrictEquals(Matcher.length, 1);
111 });
112 });
113
114 describe(".name", () => {
115 it("[[Get]] returns the correct name", () => {
116 assertStrictEquals(Matcher.name, "Matcher");
117 });
118 });
119
120 describe("::constructor", () => {
121 it("[[Get]] returns the same constructor", () => {
122 assertStrictEquals(new Matcher(/(?:)/su).constructor, Matcher);
123 });
124 });
125
126 describe("::dotAll", () => {
127 it("[[Get]] returns true when the dotAll flag is present", () => {
128 assertStrictEquals(new Matcher(/(?:)/su).dotAll, true);
129 });
130
131 it("[[Get]] returns false when the dotAll flag is not present", () => {
132 assertStrictEquals(new Matcher(/(?:)/u).dotAll, false);
133 });
134
135 describe("[[GetOwnProperty]].get.length", () => {
136 it("[[Get]] returns the correct length", () => {
137 assertStrictEquals(
138 Object.getOwnPropertyDescriptor(
139 Matcher.prototype,
140 "dotAll",
141 ).get.length,
142 0,
143 );
144 });
145 });
146
147 describe("[[GetOwnProperty]].get.name", () => {
148 it("[[Get]] returns the correct name", () => {
149 assertStrictEquals(
150 Object.getOwnPropertyDescriptor(
151 Matcher.prototype,
152 "dotAll",
153 ).get.name,
154 "get dotAll",
155 );
156 });
157 });
158 });
159
160 describe("::exec", () => {
161 it("[[Call]] returns the match object given a complete match", () => {
162 assertEquals(
163 [...new Matcher(/.(?<wow>(?:.(?=.))*)(.)?/u).exec("success")],
164 ["success", "ucces", "s"],
165 );
166 assertEquals(
167 [...new Matcher(
168 /.(?<wow>(?:.(?=.))*)(.)?/u,
169 undefined,
170 ($) => $ === "success",
171 ).exec("success")],
172 ["success", "ucces", "s"],
173 );
174 });
175
176 it("[[Call]] calls the constraint if the match succeeds", () => {
177 const constraint = spy((_) => true);
178 const matcher = new Matcher("(.).*", undefined, constraint);
179 const result = matcher.exec({
180 toString() {
181 return "etaoin";
182 },
183 });
184 assertEquals([...result], ["etaoin", "e"]);
185 assertSpyCalls(constraint, 1);
186 assertStrictEquals(constraint.calls[0].args[0], "etaoin");
187 assertEquals([...constraint.calls[0].args[1]], ["etaoin", "e"]);
188 assertStrictEquals(constraint.calls[0].args[2], matcher);
189 assertStrictEquals(constraint.calls[0].self, undefined);
190 });
191
192 it("[[Call]] does not call the constraint if the match fails", () => {
193 const constraint = spy((_) => true);
194 const matcher = new Matcher("", undefined, constraint);
195 matcher.exec("failure");
196 assertSpyCalls(constraint, 0);
197 });
198
199 it("[[Call]] returns null given a partial match", () => {
200 assertStrictEquals(new Matcher("").exec("failure"), null);
201 });
202
203 it("[[Call]] returns null if the constraint fails", () => {
204 assertStrictEquals(
205 new Matcher(".*", undefined, () => false).exec(""),
206 null,
207 );
208 });
209
210 it("[[Construct]] throws an error", () => {
211 const matcher = new Matcher("");
212 assertThrows(() => new matcher.exec());
213 });
214
215 describe(".length", () => {
216 it("[[Get]] returns the correct length", () => {
217 assertStrictEquals(Matcher.prototype.exec.length, 1);
218 });
219 });
220
221 describe(".name", () => {
222 it("[[Get]] returns the correct name", () => {
223 assertStrictEquals(Matcher.prototype.exec.name, "exec");
224 });
225 });
226 });
227
228 describe("::global", () => {
229 it("[[Get]] returns true when the global flag is present", () => {
230 assertStrictEquals(new Matcher(/(?:)/gu).global, true);
231 });
232
233 it("[[Get]] returns false when the global flag is not present", () => {
234 assertStrictEquals(new Matcher(/(?:)/u).global, false);
235 });
236
237 describe("[[GetOwnProperty]].get.length", () => {
238 it("[[Get]] returns the correct length", () => {
239 assertStrictEquals(
240 Object.getOwnPropertyDescriptor(
241 Matcher.prototype,
242 "global",
243 ).get.length,
244 0,
245 );
246 });
247 });
248
249 describe("[[GetOwnProperty]].get.name", () => {
250 it("[[Get]] returns the correct name", () => {
251 assertStrictEquals(
252 Object.getOwnPropertyDescriptor(
253 Matcher.prototype,
254 "global",
255 ).get.name,
256 "get global",
257 );
258 });
259 });
260 });
261
262 describe("::hasIndices", () => {
263 it("[[Get]] returns true when the hasIndices flag is present", () => {
264 assertStrictEquals(new Matcher(/(?:)/du).hasIndices, true);
265 });
266
267 it("[[Get]] returns false when the hasIndices flag is not present", () => {
268 assertStrictEquals(new Matcher(/(?:)/u).hasIndices, false);
269 });
270
271 describe("[[GetOwnProperty]].get.length", () => {
272 it("[[Get]] returns the correct length", () => {
273 assertStrictEquals(
274 Object.getOwnPropertyDescriptor(
275 Matcher.prototype,
276 "hasIndices",
277 ).get.length,
278 0,
279 );
280 });
281 });
282
283 describe("[[GetOwnProperty]].get.name", () => {
284 it("[[Get]] returns the correct name", () => {
285 assertStrictEquals(
286 Object.getOwnPropertyDescriptor(
287 Matcher.prototype,
288 "hasIndices",
289 ).get.name,
290 "get hasIndices",
291 );
292 });
293 });
294 });
295
296 describe("::ignoreCase", () => {
297 it("[[Get]] returns true when the ignoreCase flag is present", () => {
298 assertStrictEquals(new Matcher(/(?:)/iu).ignoreCase, true);
299 });
300
301 it("[[Get]] returns false when the ignoreCase flag is not present", () => {
302 assertStrictEquals(new Matcher(/(?:)/u).ignoreCase, false);
303 });
304
305 describe("[[GetOwnProperty]].get.length", () => {
306 it("[[Get]] returns the correct length", () => {
307 assertStrictEquals(
308 Object.getOwnPropertyDescriptor(
309 Matcher.prototype,
310 "ignoreCase",
311 ).get.length,
312 0,
313 );
314 });
315 });
316
317 describe("[[GetOwnProperty]].get.name", () => {
318 it("[[Get]] returns the correct name", () => {
319 assertStrictEquals(
320 Object.getOwnPropertyDescriptor(
321 Matcher.prototype,
322 "ignoreCase",
323 ).get.name,
324 "get ignoreCase",
325 );
326 });
327 });
328 });
329
330 describe("::multiline", () => {
331 it("[[Get]] returns true when the multiline flag is present", () => {
332 assertStrictEquals(new Matcher(/(?:)/mu).multiline, true);
333 });
334
335 it("[[Get]] returns false when the multiline flag is not present", () => {
336 assertStrictEquals(new Matcher(/(?:)/u).multiline, false);
337 });
338
339 describe("[[GetOwnProperty]].get.length", () => {
340 it("[[Get]] returns the correct length", () => {
341 assertStrictEquals(
342 Object.getOwnPropertyDescriptor(
343 Matcher.prototype,
344 "multiline",
345 ).get.length,
346 0,
347 );
348 });
349 });
350
351 describe("[[GetOwnProperty]].get.name", () => {
352 it("[[Get]] returns the correct name", () => {
353 assertStrictEquals(
354 Object.getOwnPropertyDescriptor(
355 Matcher.prototype,
356 "multiline",
357 ).get.name,
358 "get multiline",
359 );
360 });
361 });
362 });
363
364 describe("::source", () => {
365 it("[[Get]] returns the RegExp source", () => {
366 assertStrictEquals(new Matcher("").source, "(?:)");
367 assertStrictEquals(new Matcher(/.*/su).source, ".*");
368 });
369
370 describe("[[GetOwnProperty]].get.length", () => {
371 it("[[Get]] returns the correct length", () => {
372 assertStrictEquals(
373 Object.getOwnPropertyDescriptor(
374 Matcher.prototype,
375 "source",
376 ).get.length,
377 0,
378 );
379 });
380 });
381
382 describe("[[GetOwnProperty]].get.name", () => {
383 it("[[Get]] returns the correct name", () => {
384 assertStrictEquals(
385 Object.getOwnPropertyDescriptor(
386 Matcher.prototype,
387 "source",
388 ).get.name,
389 "get source",
390 );
391 });
392 });
393 });
394
395 describe("::sticky", () => {
396 it("[[Get]] returns true when the sticky flag is present", () => {
397 assertStrictEquals(new Matcher(/(?:)/uy).sticky, true);
398 });
399
400 it("[[Get]] returns false when the sticky flag is not present", () => {
401 assertStrictEquals(new Matcher(/(?:)/u).sticky, false);
402 });
403
404 describe("[[GetOwnProperty]].get.length", () => {
405 it("[[Get]] returns the correct length", () => {
406 assertStrictEquals(
407 Object.getOwnPropertyDescriptor(
408 Matcher.prototype,
409 "sticky",
410 ).get.length,
411 0,
412 );
413 });
414 });
415
416 describe("[[GetOwnProperty]].get.name", () => {
417 it("[[Get]] returns the correct name", () => {
418 assertStrictEquals(
419 Object.getOwnPropertyDescriptor(
420 Matcher.prototype,
421 "sticky",
422 ).get.name,
423 "get sticky",
424 );
425 });
426 });
427 });
428
429 describe("::toString", () => {
430 it("[[Call]] returns the string source", () => {
431 assertStrictEquals(new Matcher(/(?:)/u).toString(), "/(?:)/u");
432 });
433
434 it("[[Construct]] throws an error", () => {
435 const matcher = new Matcher("");
436 assertThrows(() => new matcher.toString());
437 });
438
439 describe(".length", () => {
440 it("[[Get]] returns the correct length", () => {
441 assertStrictEquals(Matcher.prototype.toString.length, 0);
442 });
443 });
444
445 describe(".name", () => {
446 it("[[Get]] returns the correct name", () => {
447 assertStrictEquals(
448 Matcher.prototype.toString.name,
449 "toString",
450 );
451 });
452 });
453 });
454
455 describe("::unicode", () => {
456 it("[[Get]] returns true when the unicode flag is present", () => {
457 assertStrictEquals(new Matcher(/(?:)/u).unicode, true);
458 });
459
460 describe("[[GetOwnProperty]].get.length", () => {
461 it("[[Get]] returns the correct length", () => {
462 assertStrictEquals(
463 Object.getOwnPropertyDescriptor(
464 Matcher.prototype,
465 "unicode",
466 ).get.length,
467 0,
468 );
469 });
470 });
471
472 describe("[[GetOwnProperty]].get.name", () => {
473 it("[[Get]] returns the correct name", () => {
474 assertStrictEquals(
475 Object.getOwnPropertyDescriptor(
476 Matcher.prototype,
477 "unicode",
478 ).get.name,
479 "get unicode",
480 );
481 });
482 });
483 });
484
485 describe("::unicodeSets", () => {
486 it("[[Get]] returns true when the unicode sets flag is present", () => {
487 assertStrictEquals(new Matcher(/(?:)/v).unicodeSets, true);
488 });
489
490 describe("[[GetOwnProperty]].get.length", () => {
491 it("[[Get]] returns the correct length", () => {
492 assertStrictEquals(
493 Object.getOwnPropertyDescriptor(
494 Matcher.prototype,
495 "unicodeSets",
496 ).get.length,
497 0,
498 );
499 });
500 });
501
502 describe("[[GetOwnProperty]].get.name", () => {
503 it("[[Get]] returns the correct name", () => {
504 assertStrictEquals(
505 Object.getOwnPropertyDescriptor(
506 Matcher.prototype,
507 "unicodeSets",
508 ).get.name,
509 "get unicodeSets",
510 );
511 });
512 });
513 });
514
515 describe("~", () => {
516 it("[[Call]] returns true for a complete match", () => {
517 assertStrictEquals(new Matcher("")(""), true);
518 assertStrictEquals(new Matcher(/.*/su)("success\nyay"), true);
519 assertStrictEquals(
520 new Matcher(/.*/su, undefined, ($) => $ === "success")(
521 "success",
522 ),
523 true,
524 );
525 });
526
527 it("[[Call]] calls the constraint if the match succeeds", () => {
528 const constraint = spy((_) => true);
529 const matcher = new Matcher("(.).*", undefined, constraint);
530 matcher("etaoin");
531 assertSpyCalls(constraint, 1);
532 assertStrictEquals(constraint.calls[0].args[0], "etaoin");
533 assertEquals([...constraint.calls[0].args[1]], ["etaoin", "e"]);
534 assertStrictEquals(constraint.calls[0].args[2], matcher);
535 assertStrictEquals(constraint.calls[0].self, undefined);
536 });
537
538 it("[[Call]] does not call the constraint if the match fails", () => {
539 const constraint = spy((_) => true);
540 const matcher = new Matcher("", undefined, constraint);
541 matcher("failure");
542 assertSpyCalls(constraint, 0);
543 });
544
545 it("[[Call]] returns false for a partial match", () => {
546 assertStrictEquals(new Matcher("")("failure"), false);
547 assertStrictEquals(new Matcher(/.*/u)("failure\nno"), false);
548 });
549
550 it("[[Call]] returns false if the constraint fails", () => {
551 assertStrictEquals(
552 new Matcher(".*", undefined, () => false)(""),
553 false,
554 );
555 });
556
557 it("[[Construct]] throws an error", () => {
558 const matcher = new Matcher("");
559 assertThrows(() => new matcher(""));
560 });
561 });
562
563 describe("~lastIndex", () => {
564 it("[[Get]] returns zero", () => {
565 assertStrictEquals(new Matcher("").lastIndex, 0);
566 });
567
568 it("[[Set]] fails", () => {
569 assertThrows(() => (new Matcher("").lastIndex = 1));
570 });
571 });
572
573 describe("~length", () => {
574 it("[[Get]] returns one", () => {
575 assertStrictEquals(new Matcher("").length, 1);
576 });
577 });
578
579 describe("~name", () => {
580 it("[[Get]] wraps the stringified regular expression if no name was provided", () => {
581 assertStrictEquals(new Matcher("").name, "Matcher(/(?:)/u)");
582 assertStrictEquals(
583 new Matcher(/.*/gsu).name,
584 "Matcher(/.*/gsu)",
585 );
586 });
587
588 it("[[Get]] uses the provided name if one was provided", () => {
589 assertStrictEquals(new Matcher("", "success").name, "success");
590 });
591 });
592 });
593
594 describe("asciiLowercase", () => {
595 it("[[Call]] lowercases (just) A·S·C·I·I letters", () => {
596 assertStrictEquals(asciiLowercase("aBſÆss FtɁɂß"), "abſÆss ftɁɂß");
597 });
598
599 it("[[Construct]] throws an error", () => {
600 assertThrows(() => new asciiLowercase(""));
601 });
602
603 describe(".length", () => {
604 it("[[Get]] returns the correct length", () => {
605 assertStrictEquals(asciiLowercase.length, 1);
606 });
607 });
608
609 describe(".name", () => {
610 it("[[Get]] returns the correct name", () => {
611 assertStrictEquals(asciiLowercase.name, "asciiLowercase");
612 });
613 });
614 });
615
616 describe("asciiUppercase", () => {
617 it("[[Call]] uppercases (just) A·S·C·I·I letters", () => {
618 assertStrictEquals(asciiUppercase("aBſÆss FtɁɂß"), "ABſÆSS FTɁɂß");
619 });
620
621 it("[[Construct]] throws an error", () => {
622 assertThrows(() => new asciiUppercase(""));
623 });
624
625 describe(".length", () => {
626 it("[[Get]] returns the correct length", () => {
627 assertStrictEquals(asciiUppercase.length, 1);
628 });
629 });
630
631 describe(".name", () => {
632 it("[[Get]] returns the correct name", () => {
633 assertStrictEquals(asciiUppercase.name, "asciiUppercase");
634 });
635 });
636 });
637
638 describe("canonicalNumericIndexString", () => {
639 it("[[Call]] returns undefined for nonstrings", () => {
640 assertStrictEquals(canonicalNumericIndexString(1), void {});
641 });
642
643 it("[[Call]] returns undefined for noncanonical strings", () => {
644 assertStrictEquals(canonicalNumericIndexString(""), void {});
645 assertStrictEquals(canonicalNumericIndexString("01"), void {});
646 assertStrictEquals(
647 canonicalNumericIndexString("9007199254740993"),
648 void {},
649 );
650 });
651
652 it('[[Call]] returns -0 for "-0"', () => {
653 assertStrictEquals(canonicalNumericIndexString("-0"), -0);
654 });
655
656 it("[[Call]] returns the corresponding number for canonical strings", () => {
657 assertStrictEquals(canonicalNumericIndexString("0"), 0);
658 assertStrictEquals(canonicalNumericIndexString("-0.25"), -0.25);
659 assertStrictEquals(
660 canonicalNumericIndexString("9007199254740992"),
661 9007199254740992,
662 );
663 assertStrictEquals(canonicalNumericIndexString("NaN"), 0 / 0);
664 assertStrictEquals(canonicalNumericIndexString("Infinity"), 1 / 0);
665 assertStrictEquals(
666 canonicalNumericIndexString("-Infinity"),
667 -1 / 0,
668 );
669 });
670
671 it("[[Construct]] throws an error", () => {
672 assertThrows(() => new canonicalNumericIndexString(""));
673 });
674
675 describe(".length", () => {
676 it("[[Get]] returns the correct length", () => {
677 assertStrictEquals(canonicalNumericIndexString.length, 1);
678 });
679 });
680
681 describe(".name", () => {
682 it("[[Get]] returns the correct name", () => {
683 assertStrictEquals(
684 canonicalNumericIndexString.name,
685 "canonicalNumericIndexString",
686 );
687 });
688 });
689 });
690
691 describe("characters", () => {
692 it("[[Call]] returns an iterable", () => {
693 assertStrictEquals(
694 typeof characters("")[Symbol.iterator],
695 "function",
696 );
697 });
698
699 it("[[Call]] returns an iterator", () => {
700 assertStrictEquals(typeof characters("").next, "function");
701 });
702
703 it("[[Call]] returns a string character iterator", () => {
704 assertStrictEquals(
705 characters("")[Symbol.toStringTag],
706 "String Character Iterator",
707 );
708 });
709
710 it("[[Call]] iterates over the characters", () => {
711 assertEquals([
712 ...characters("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
713 ], [
714 "I",
715 "i",
716 "🎙",
717 "\uDFFF",
718 "\uDD96",
719 "\uD83C",
720 "\uD800",
721 "🆗",
722 "☺",
723 ]);
724 });
725
726 it("[[Construct]] throws an error", () => {
727 assertThrows(() => new characters(""));
728 });
729
730 describe(".length", () => {
731 it("[[Get]] returns the correct length", () => {
732 assertStrictEquals(characters.length, 1);
733 });
734 });
735
736 describe(".name", () => {
737 it("[[Get]] returns the correct name", () => {
738 assertStrictEquals(characters.name, "characters");
739 });
740 });
741 });
742
743 describe("codeUnits", () => {
744 it("[[Call]] returns an iterable", () => {
745 assertStrictEquals(
746 typeof codeUnits("")[Symbol.iterator],
747 "function",
748 );
749 });
750
751 it("[[Call]] returns an iterator", () => {
752 assertStrictEquals(typeof codeUnits("").next, "function");
753 });
754
755 it("[[Call]] returns a string code unit iterator", () => {
756 assertStrictEquals(
757 codeUnits("")[Symbol.toStringTag],
758 "String Code Unit Iterator",
759 );
760 });
761
762 it("[[Call]] iterates over the code units", () => {
763 assertEquals([
764 ...codeUnits("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
765 ], [
766 0x49,
767 0x69,
768 0xD83C,
769 0xDF99,
770 0xDFFF,
771 0xDD96,
772 0xD83C,
773 0xD800,
774 0xD83C,
775 0xDD97,
776 0x263A,
777 ]);
778 });
779
780 it("[[Construct]] throws an error", () => {
781 assertThrows(() => new codeUnits(""));
782 });
783
784 describe(".length", () => {
785 it("[[Get]] returns the correct length", () => {
786 assertStrictEquals(codeUnits.length, 1);
787 });
788 });
789
790 describe(".name", () => {
791 it("[[Get]] returns the correct name", () => {
792 assertStrictEquals(codeUnits.name, "codeUnits");
793 });
794 });
795 });
796
797 describe("codepoints", () => {
798 it("[[Call]] returns an iterable", () => {
799 assertStrictEquals(
800 typeof codepoints("")[Symbol.iterator],
801 "function",
802 );
803 });
804
805 it("[[Call]] returns an iterator", () => {
806 assertStrictEquals(typeof codepoints("").next, "function");
807 });
808
809 it("[[Call]] returns a string codepoint iterator", () => {
810 assertStrictEquals(
811 codepoints("")[Symbol.toStringTag],
812 "String Codepoint Iterator",
813 );
814 });
815
816 it("[[Call]] iterates over the codepoints", () => {
817 assertEquals([
818 ...codepoints("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
819 ], [
820 0x49,
821 0x69,
822 0x1F399,
823 0xDFFF,
824 0xDD96,
825 0xD83C,
826 0xD800,
827 0x1F197,
828 0x263A,
829 ]);
830 });
831
832 it("[[Construct]] throws an error", () => {
833 assertThrows(() => new codepoints(""));
834 });
835
836 describe(".length", () => {
837 it("[[Get]] returns the correct length", () => {
838 assertStrictEquals(codepoints.length, 1);
839 });
840 });
841
842 describe(".name", () => {
843 it("[[Get]] returns the correct name", () => {
844 assertStrictEquals(codepoints.name, "codepoints");
845 });
846 });
847 });
848
849 describe("getCharacter", () => {
850 it("[[Call]] returns the character at the provided position", () => {
851 assertStrictEquals(getCharacter("Ii🎙🆗☺", 4), "🆗");
852 });
853
854 it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
855 assertStrictEquals(getCharacter("Ii🎙🆗☺", 5), "\uDD97");
856 });
857
858 it("[[Call]] returns undefined for an out‐of‐bounds index", () => {
859 assertStrictEquals(getCharacter("Ii🎙🆗☺", -1), undefined);
860 assertStrictEquals(getCharacter("Ii🎙🆗☺", 7), undefined);
861 });
862
863 it("[[Construct]] throws an error", () => {
864 assertThrows(() => new getCharacter("a", 0));
865 });
866
867 describe(".length", () => {
868 it("[[Get]] returns the correct length", () => {
869 assertStrictEquals(getCharacter.length, 2);
870 });
871 });
872
873 describe(".name", () => {
874 it("[[Get]] returns the correct name", () => {
875 assertStrictEquals(getCharacter.name, "getCharacter");
876 });
877 });
878 });
879
880 describe("getCodeUnit", () => {
881 it("[[Call]] returns the code unit at the provided position", () => {
882 assertStrictEquals(getCodeUnit("Ii🎙🆗☺", 4), 0xD83C);
883 });
884
885 it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
886 assertStrictEquals(getCodeUnit("Ii🎙🆗☺", 5), 0xDD97);
887 });
888
889 it("[[Call]] returns undefined for an out‐of‐bounds index", () => {
890 assertStrictEquals(getCodeUnit("Ii🎙🆗☺", -1), undefined);
891 assertStrictEquals(getCodeUnit("Ii🎙🆗☺", 7), undefined);
892 });
893
894 it("[[Construct]] throws an error", () => {
895 assertThrows(() => new getCodeUnit("a", 0));
896 });
897
898 describe(".length", () => {
899 it("[[Get]] returns the correct length", () => {
900 assertStrictEquals(getCodeUnit.length, 2);
901 });
902 });
903
904 describe(".name", () => {
905 it("[[Get]] returns the correct name", () => {
906 assertStrictEquals(getCodeUnit.name, "getCodeUnit");
907 });
908 });
909 });
910
911 describe("getCodepoint", () => {
912 it("[[Call]] returns the character at the provided position", () => {
913 assertStrictEquals(getCodepoint("Ii🎙🆗☺", 4), 0x1F197);
914 });
915
916 it("[[Call]] returns a low surrogate if the provided position splits a character", () => {
917 assertStrictEquals(getCodepoint("Ii🎙🆗☺", 5), 0xDD97);
918 });
919
920 it("[[Call]] returns undefined for an out‐of‐bounds index", () => {
921 assertStrictEquals(getCodepoint("Ii🎙🆗☺", -1), undefined);
922 assertStrictEquals(getCodepoint("Ii🎙🆗☺", 7), undefined);
923 });
924
925 it("[[Construct]] throws an error", () => {
926 assertThrows(() => new getCodepoint("a", 0));
927 });
928
929 describe(".length", () => {
930 it("[[Get]] returns the correct length", () => {
931 assertStrictEquals(getCodepoint.length, 2);
932 });
933 });
934
935 describe(".name", () => {
936 it("[[Get]] returns the correct name", () => {
937 assertStrictEquals(getCodepoint.name, "getCodepoint");
938 });
939 });
940 });
941
942 describe("getFirstSubstringIndex", () => {
943 it("[[Call]] returns the index of the first match", () => {
944 assertStrictEquals(getFirstSubstringIndex("Ii🎙🆗☺🆗", "🆗"), 4);
945 });
946
947 it("[[Call]] returns −1 if no match is found", () => {
948 assertStrictEquals(getFirstSubstringIndex("Ii🎙🆗☺🆗", "🆗🆖"), -1);
949 });
950
951 it("[[Call]] returns 0 when provided with an empty string", () => {
952 assertStrictEquals(getFirstSubstringIndex("Ii🎙🆗☺🆗", ""), 0);
953 });
954
955 it("[[Construct]] throws an error", () => {
956 assertThrows(() => new getFirstSubstringIndex("", ""));
957 });
958
959 describe(".length", () => {
960 it("[[Get]] returns the correct length", () => {
961 assertStrictEquals(getFirstSubstringIndex.length, 2);
962 });
963 });
964
965 describe(".name", () => {
966 it("[[Get]] returns the correct name", () => {
967 assertStrictEquals(
968 getFirstSubstringIndex.name,
969 "getFirstSubstringIndex",
970 );
971 });
972 });
973 });
974
975 describe("getLastSubstringIndex", () => {
976 it("[[Call]] returns the index of the first match", () => {
977 assertStrictEquals(getLastSubstringIndex("Ii🎙🆗☺🆗", "🆗"), 7);
978 });
979
980 it("[[Call]] returns −1 if no match is found", () => {
981 assertStrictEquals(getLastSubstringIndex("Ii🎙🆗☺🆗", "🆖🆗"), -1);
982 });
983
984 it("[[Call]] returns the length when provided with an empty string", () => {
985 assertStrictEquals(
986 getLastSubstringIndex("Ii🎙🆗☺🆗", ""),
987 "Ii🎙🆗☺🆗".length,
988 );
989 });
990
991 it("[[Construct]] throws an error", () => {
992 assertThrows(() => new getLastSubstringIndex("", ""));
993 });
994
995 describe(".length", () => {
996 it("[[Get]] returns the correct length", () => {
997 assertStrictEquals(getLastSubstringIndex.length, 2);
998 });
999 });
1000
1001 describe(".name", () => {
1002 it("[[Get]] returns the correct name", () => {
1003 assertStrictEquals(
1004 getLastSubstringIndex.name,
1005 "getLastSubstringIndex",
1006 );
1007 });
1008 });
1009 });
1010
1011 describe("isArrayIndexString", () => {
1012 it("[[Call]] returns false for nonstrings", () => {
1013 assertStrictEquals(isArrayIndexString(1), false);
1014 });
1015
1016 it("[[Call]] returns false for noncanonical strings", () => {
1017 assertStrictEquals(isArrayIndexString(""), false);
1018 assertStrictEquals(isArrayIndexString("01"), false);
1019 assertStrictEquals(isArrayIndexString("9007199254740993"), false);
1020 });
1021
1022 it("[[Call]] returns false for nonfinite numbers", () => {
1023 assertStrictEquals(isArrayIndexString("NaN"), false);
1024 assertStrictEquals(isArrayIndexString("Infinity"), false);
1025 assertStrictEquals(isArrayIndexString("-Infinity"), false);
1026 });
1027
1028 it("[[Call]] returns false for negative numbers", () => {
1029 assertStrictEquals(isArrayIndexString("-0"), false);
1030 assertStrictEquals(isArrayIndexString("-1"), false);
1031 });
1032
1033 it("[[Call]] returns false for nonintegers", () => {
1034 assertStrictEquals(isArrayIndexString("0.25"), false);
1035 assertStrictEquals(isArrayIndexString("1.1"), false);
1036 });
1037
1038 it("[[Call]] returns false for numbers greater than or equal to -1 >>> 0", () => {
1039 assertStrictEquals(isArrayIndexString(String(-1 >>> 0)), false);
1040 assertStrictEquals(
1041 isArrayIndexString(String((-1 >>> 0) + 1)),
1042 false,
1043 );
1044 });
1045
1046 it("[[Call]] returns true for array lengths less than -1 >>> 0", () => {
1047 assertStrictEquals(isArrayIndexString("0"), true);
1048 assertStrictEquals(
1049 isArrayIndexString(String((-1 >>> 0) - 1)),
1050 true,
1051 );
1052 });
1053
1054 it("[[Construct]] throws an error", () => {
1055 assertThrows(() => new isArrayIndexString("0"));
1056 });
1057
1058 describe(".length", () => {
1059 it("[[Get]] returns the correct length", () => {
1060 assertStrictEquals(isArrayIndexString.length, 1);
1061 });
1062 });
1063
1064 describe(".name", () => {
1065 it("[[Get]] returns the correct name", () => {
1066 assertStrictEquals(
1067 isArrayIndexString.name,
1068 "isArrayIndexString",
1069 );
1070 });
1071 });
1072 });
1073
1074 describe("isIntegerIndexString", () => {
1075 it("[[Call]] returns false for nonstrings", () => {
1076 assertStrictEquals(isIntegerIndexString(1), false);
1077 });
1078
1079 it("[[Call]] returns false for noncanonical strings", () => {
1080 assertStrictEquals(isIntegerIndexString(""), false);
1081 assertStrictEquals(isIntegerIndexString("01"), false);
1082 assertStrictEquals(
1083 isIntegerIndexString("9007199254740993"),
1084 false,
1085 );
1086 });
1087
1088 it("[[Call]] returns false for nonfinite numbers", () => {
1089 assertStrictEquals(isIntegerIndexString("NaN"), false);
1090 assertStrictEquals(isIntegerIndexString("Infinity"), false);
1091 assertStrictEquals(isIntegerIndexString("-Infinity"), false);
1092 });
1093
1094 it("[[Call]] returns false for negative numbers", () => {
1095 assertStrictEquals(isIntegerIndexString("-0"), false);
1096 assertStrictEquals(isIntegerIndexString("-1"), false);
1097 });
1098
1099 it("[[Call]] returns false for nonintegers", () => {
1100 assertStrictEquals(isIntegerIndexString("0.25"), false);
1101 assertStrictEquals(isIntegerIndexString("1.1"), false);
1102 });
1103
1104 it("[[Call]] returns false for numbers greater than or equal to 2 ** 53", () => {
1105 assertStrictEquals(
1106 isIntegerIndexString("9007199254740992"),
1107 false,
1108 );
1109 });
1110
1111 it("[[Call]] returns true for safe canonical integer strings", () => {
1112 assertStrictEquals(isIntegerIndexString("0"), true);
1113 assertStrictEquals(isIntegerIndexString("9007199254740991"), true);
1114 });
1115
1116 it("[[Construct]] throws an error", () => {
1117 assertThrows(() => new isIntegerIndexString("0"));
1118 });
1119
1120 describe(".length", () => {
1121 it("[[Get]] returns the correct length", () => {
1122 assertStrictEquals(isIntegerIndexString.length, 1);
1123 });
1124 });
1125
1126 describe(".name", () => {
1127 it("[[Get]] returns the correct name", () => {
1128 assertStrictEquals(
1129 isIntegerIndexString.name,
1130 "isIntegerIndexString",
1131 );
1132 });
1133 });
1134 });
1135
1136 describe("join", () => {
1137 it("[[Call]] joins the provided iterator with the provided separartor", () => {
1138 assertStrictEquals(join([1, 2, 3, 4].values(), "☂"), "1☂2☂3☂4");
1139 });
1140
1141 it('[[Call]] uses "," if no separator is provided', () => {
1142 assertStrictEquals(join([1, 2, 3, 4].values()), "1,2,3,4");
1143 });
1144
1145 it("[[Call]] uses the empty sting for nullish values", () => {
1146 assertStrictEquals(
1147 join([null, , null, undefined].values(), "☂"),
1148 "☂☂☂",
1149 );
1150 });
1151
1152 it("[[Construct]] throws an error", () => {
1153 assertThrows(() => new join([]));
1154 });
1155
1156 describe(".length", () => {
1157 it("[[Get]] returns the correct length", () => {
1158 assertStrictEquals(join.length, 2);
1159 });
1160 });
1161
1162 describe(".name", () => {
1163 it("[[Get]] returns the correct name", () => {
1164 assertStrictEquals(join.name, "join");
1165 });
1166 });
1167 });
1168
1169 describe("rawString", () => {
1170 it("[[Call]] acts like String.raw", () => {
1171 assertStrictEquals(rawString`\nraw${" string"}`, "\\nraw string");
1172 });
1173
1174 it("[[Construct]] throws an error", () => {
1175 assertThrows(() => new rawString(["string"]));
1176 });
1177
1178 describe(".length", () => {
1179 it("[[Get]] returns the correct length", () => {
1180 assertStrictEquals(rawString.length, 1);
1181 });
1182 });
1183
1184 describe(".name", () => {
1185 it("[[Get]] returns the correct name", () => {
1186 assertStrictEquals(rawString.name, "rawString");
1187 });
1188 });
1189 });
1190
1191 describe("scalarValues", () => {
1192 it("[[Call]] returns an iterable", () => {
1193 assertStrictEquals(
1194 typeof scalarValues("")[Symbol.iterator],
1195 "function",
1196 );
1197 });
1198
1199 it("[[Call]] returns an iterator", () => {
1200 assertStrictEquals(typeof scalarValues("").next, "function");
1201 });
1202
1203 it("[[Call]] returns a string scalar value iterator", () => {
1204 assertStrictEquals(
1205 scalarValues("")[Symbol.toStringTag],
1206 "String Scalar Value Iterator",
1207 );
1208 });
1209
1210 it("[[Call]] iterates over the scalar values", () => {
1211 assertEquals([
1212 ...scalarValues("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
1213 ], [
1214 0x49,
1215 0x69,
1216 0x1F399,
1217 0xFFFD,
1218 0xFFFD,
1219 0xFFFD,
1220 0xFFFD,
1221 0x1F197,
1222 0x263A,
1223 ]);
1224 });
1225
1226 it("[[Construct]] throws an error", () => {
1227 assertThrows(() => new scalarValues(""));
1228 });
1229
1230 describe(".length", () => {
1231 it("[[Get]] returns the correct length", () => {
1232 assertStrictEquals(scalarValues.length, 1);
1233 });
1234 });
1235
1236 describe(".name", () => {
1237 it("[[Get]] returns the correct name", () => {
1238 assertStrictEquals(scalarValues.name, "scalarValues");
1239 });
1240 });
1241 });
1242
1243 describe("splitOnAsciiWhitespace", () => {
1244 it("[[Call]] splits on sequences of spaces", () => {
1245 assertEquals(
1246 splitOnAsciiWhitespace("🅰️ 🅱️ 🆎 🅾️"),
1247 ["🅰️", "🅱️", "🆎", "🅾️"],
1248 );
1249 });
1250
1251 it("[[Call]] splits on sequences of tabs", () => {
1252 assertEquals(
1253 splitOnAsciiWhitespace("🅰️\t\t\t🅱️\t🆎\t\t🅾️"),
1254 ["🅰️", "🅱️", "🆎", "🅾️"],
1255 );
1256 });
1257
1258 it("[[Call]] splits on sequences of carriage returns", () => {
1259 assertEquals(
1260 splitOnAsciiWhitespace("🅰️\r\r\r🅱️\r🆎\r\r🅾️"),
1261 ["🅰️", "🅱️", "🆎", "🅾️"],
1262 );
1263 });
1264
1265 it("[[Call]] splits on sequences of newlines", () => {
1266 assertEquals(
1267 splitOnAsciiWhitespace("🅰️\r\r\r🅱️\r🆎\r\r🅾️"),
1268 ["🅰️", "🅱️", "🆎", "🅾️"],
1269 );
1270 });
1271
1272 it("[[Call]] splits on sequences of form feeds", () => {
1273 assertEquals(
1274 splitOnAsciiWhitespace("🅰️\f\f\f🅱️\f🆎\f\f🅾️"),
1275 ["🅰️", "🅱️", "🆎", "🅾️"],
1276 );
1277 });
1278
1279 it("[[Call]] splits on mixed whitespace", () => {
1280 assertEquals(
1281 splitOnAsciiWhitespace("🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️"),
1282 ["🅰️", "🅱️", "🆎", "🅾️"],
1283 );
1284 });
1285
1286 it("[[Call]] returns an array of just the empty string for the empty string", () => {
1287 assertEquals(splitOnAsciiWhitespace(""), [""]);
1288 });
1289
1290 it("[[Call]] returns a single token if there are no spaces", () => {
1291 assertEquals(splitOnAsciiWhitespace("abcd"), ["abcd"]);
1292 });
1293
1294 it("[[Call]] does not split on other kinds of whitespace", () => {
1295 assertEquals(
1296 splitOnAsciiWhitespace("a\u202F\u205F\xa0\v\0\bb"),
1297 ["a\u202F\u205F\xa0\v\0\bb"],
1298 );
1299 });
1300
1301 it("[[Call]] trims leading and trailing whitespace", () => {
1302 assertEquals(
1303 splitOnAsciiWhitespace(
1304 "\f\r\n\r\n \n\t🅰️\f \t\n🅱️\r🆎\n\f🅾️\n\f",
1305 ),
1306 ["🅰️", "🅱️", "🆎", "🅾️"],
1307 );
1308 });
1309
1310 it("[[Construct]] throws an error", () => {
1311 assertThrows(() => new splitOnAsciiWhitespace(""));
1312 });
1313
1314 describe(".length", () => {
1315 it("[[Get]] returns the correct length", () => {
1316 assertStrictEquals(splitOnAsciiWhitespace.length, 1);
1317 });
1318 });
1319
1320 describe(".name", () => {
1321 it("[[Get]] returns the correct name", () => {
1322 assertStrictEquals(
1323 splitOnAsciiWhitespace.name,
1324 "splitOnAsciiWhitespace",
1325 );
1326 });
1327 });
1328 });
1329
1330 describe("splitOnCommas", () => {
1331 it("[[Call]] splits on commas", () => {
1332 assertEquals(
1333 splitOnCommas("🅰️,🅱️,🆎,🅾️"),
1334 ["🅰️", "🅱️", "🆎", "🅾️"],
1335 );
1336 });
1337
1338 it("[[Call]] returns an array of just the empty string for the empty string", () => {
1339 assertEquals(splitOnCommas(""), [""]);
1340 });
1341
1342 it("[[Call]] returns a single token if there are no commas", () => {
1343 assertEquals(splitOnCommas("abcd"), ["abcd"]);
1344 });
1345
1346 it("[[Call]] splits into empty strings if there are only commas", () => {
1347 assertEquals(splitOnCommas(",,,"), ["", "", "", ""]);
1348 });
1349
1350 it("[[Call]] trims leading and trailing whitespace", () => {
1351 assertEquals(
1352 splitOnCommas("\f\r\n\r\n \n\t🅰️,🅱️,🆎,🅾️\n\f"),
1353 ["🅰️", "🅱️", "🆎", "🅾️"],
1354 );
1355 assertEquals(
1356 splitOnCommas("\f\r\n\r\n \n\t,,,\n\f"),
1357 ["", "", "", ""],
1358 );
1359 });
1360
1361 it("[[Call]] removes whitespace from the split tokens", () => {
1362 assertEquals(
1363 splitOnCommas(
1364 "\f\r\n\r\n \n\t🅰️\f , \t\n🅱️,\r\n\r🆎\n\f,🅾️\n\f",
1365 ),
1366 ["🅰️", "🅱️", "🆎", "🅾️"],
1367 );
1368 assertEquals(
1369 splitOnCommas("\f\r\n\r\n \n\t\f , \t\n,\r\n\r\n\f,\n\f"),
1370 ["", "", "", ""],
1371 );
1372 });
1373
1374 it("[[Construct]] throws an error", () => {
1375 assertThrows(() => new splitOnCommas(""));
1376 });
1377
1378 describe(".length", () => {
1379 it("[[Get]] returns the correct length", () => {
1380 assertStrictEquals(splitOnCommas.length, 1);
1381 });
1382 });
1383
1384 describe(".name", () => {
1385 it("[[Get]] returns the correct name", () => {
1386 assertStrictEquals(splitOnCommas.name, "splitOnCommas");
1387 });
1388 });
1389 });
1390
1391 describe("stringCatenate", () => {
1392 it("[[Call]] catenates the values", () => {
1393 assertStrictEquals(stringCatenate("the", " values"), "the values");
1394 });
1395
1396 it("[[Call]] returns an empty string when called with no values", () => {
1397 assertStrictEquals(stringCatenate(), "");
1398 });
1399
1400 it('[[Call]] uses "undefined" when explicitly provided undefined', () => {
1401 assertStrictEquals(
1402 stringCatenate(undefined, undefined),
1403 "undefinedundefined",
1404 );
1405 });
1406
1407 it('[[Call]] uses "null" when provided null', () => {
1408 assertStrictEquals(stringCatenate(null, null), "nullnull");
1409 });
1410
1411 it("[[Construct]] throws an error", () => {
1412 assertThrows(() => new stringCatenate());
1413 });
1414
1415 describe(".length", () => {
1416 it("[[Get]] returns the correct length", () => {
1417 assertStrictEquals(stringCatenate.length, 2);
1418 });
1419 });
1420
1421 describe(".name", () => {
1422 it("[[Get]] returns the correct name", () => {
1423 assertStrictEquals(stringCatenate.name, "stringCatenate");
1424 });
1425 });
1426 });
1427
1428 describe("stringEndsWith", () => {
1429 it("[[Call]] returns whether the string ends with the thing", () => {
1430 assertStrictEquals(
1431 stringEndsWith("very success", " success"),
1432 true,
1433 );
1434 assertStrictEquals(stringEndsWith("very fail", " success"), false);
1435 });
1436
1437 it("[[Call]] accepts an offset", () => {
1438 assertStrictEquals(
1439 stringEndsWith("very successful", " success", 12),
1440 true,
1441 );
1442 });
1443
1444 it("[[Call]] returns true for an empty string test", () => {
1445 assertStrictEquals(stringEndsWith("", ""), true);
1446 });
1447
1448 it("[[Construct]] throws an error", () => {
1449 assertThrows(() => new stringEndsWith("", ""));
1450 });
1451
1452 describe(".length", () => {
1453 it("[[Get]] returns the correct length", () => {
1454 assertStrictEquals(stringEndsWith.length, 2);
1455 });
1456 });
1457
1458 describe(".name", () => {
1459 it("[[Get]] returns the correct name", () => {
1460 assertStrictEquals(stringEndsWith.name, "stringEndsWith");
1461 });
1462 });
1463 });
1464
1465 describe("stringFromCodeUnits", () => {
1466 it("[[Call]] makes the string", () => {
1467 assertStrictEquals(
1468 stringFromCodeUnits(0xD83C, 0xDD97),
1469 "🆗",
1470 );
1471 });
1472
1473 it("[[Call]] throws with non‐integral arguments", () => {
1474 assertThrows(() => stringFromCodeUnits(NaN));
1475 assertThrows(() => stringFromCodeUnits(Infinity));
1476 assertThrows(() => stringFromCodeUnits(0.1));
1477 });
1478
1479 it("[[Call]] throws with arguments out of range", () => {
1480 assertThrows(() => stringFromCodeUnits(-1));
1481 assertThrows(() => stringFromCodeUnits(0x10000));
1482 });
1483
1484 it("[[Construct]] throws an error", () => {
1485 assertThrows(() => new stringFromCodeUnits([]));
1486 });
1487
1488 describe(".length", () => {
1489 it("[[Get]] returns the correct length", () => {
1490 assertStrictEquals(stringFromCodeUnits.length, 1);
1491 });
1492 });
1493
1494 describe(".name", () => {
1495 it("[[Get]] returns the correct name", () => {
1496 assertStrictEquals(
1497 stringFromCodeUnits.name,
1498 "stringFromCodeUnits",
1499 );
1500 });
1501 });
1502 });
1503
1504 describe("stringFromCodepoints", () => {
1505 it("[[Call]] makes the string", () => {
1506 assertStrictEquals(stringFromCodepoints(0x1F197), "🆗");
1507 });
1508
1509 it("[[Call]] throws with non‐integral arguments", () => {
1510 assertThrows(() => stringFromCodepoints(NaN));
1511 assertThrows(() => stringFromCodepoints(Infinity));
1512 assertThrows(() => stringFromCodepoints(0.1));
1513 });
1514
1515 it("[[Call]] throws with arguments out of range", () => {
1516 assertThrows(() => stringFromCodepoints(-1));
1517 assertThrows(() => stringFromCodepoints(0x110000));
1518 });
1519
1520 it("[[Construct]] throws an error", () => {
1521 assertThrows(() => new stringFromCodepoints([]));
1522 });
1523
1524 describe(".length", () => {
1525 it("[[Get]] returns the correct length", () => {
1526 assertStrictEquals(stringFromCodepoints.length, 1);
1527 });
1528 });
1529
1530 describe(".name", () => {
1531 it("[[Get]] returns the correct name", () => {
1532 assertStrictEquals(
1533 stringFromCodepoints.name,
1534 "stringFromCodepoints",
1535 );
1536 });
1537 });
1538 });
1539
1540 describe("stringIncludes", () => {
1541 it("[[Call]] returns whether the string includes the thing", () => {
1542 assertStrictEquals(
1543 stringIncludes("very success full", " success "),
1544 true,
1545 );
1546 assertStrictEquals(
1547 stringIncludes("very fail full", " success "),
1548 false,
1549 );
1550 });
1551
1552 it("[[Call]] accepts an offset", () => {
1553 assertStrictEquals(
1554 stringIncludes("maybe success full", " success ", 4),
1555 true,
1556 );
1557 assertStrictEquals(
1558 stringIncludes("maybe success full", " success ", 5),
1559 true,
1560 );
1561 assertStrictEquals(
1562 stringIncludes("maybe success full", " success ", 6),
1563 false,
1564 );
1565 });
1566
1567 it("[[Call]] returns true for an empty string test", () => {
1568 assertStrictEquals(stringIncludes("", ""), true);
1569 });
1570
1571 it("[[Construct]] throws an error", () => {
1572 assertThrows(() => new stringIncludes("", ""));
1573 });
1574
1575 describe(".length", () => {
1576 it("[[Get]] returns the correct length", () => {
1577 assertStrictEquals(stringIncludes.length, 2);
1578 });
1579 });
1580
1581 describe(".name", () => {
1582 it("[[Get]] returns the correct name", () => {
1583 assertStrictEquals(stringIncludes.name, "stringIncludes");
1584 });
1585 });
1586 });
1587
1588 describe("stringMatch", () => {
1589 it("[[Call]] does the match akin to String::match", () => {
1590 assertEquals(
1591 [...stringMatch("very success full", /([sc]+[ue]?)+/)],
1592 ["success", "ss"],
1593 );
1594 assertEquals(
1595 [...stringMatch("very success full", /([sc]+)[ue]?/g)],
1596 ["su", "cce", "ss"],
1597 );
1598 });
1599
1600 it("[[Construct]] throws an error", () => {
1601 assertThrows(() => new stringMatch("", /(?:)/));
1602 });
1603
1604 describe(".length", () => {
1605 it("[[Get]] returns the correct length", () => {
1606 assertStrictEquals(stringMatch.length, 2);
1607 });
1608 });
1609
1610 describe(".name", () => {
1611 it("[[Get]] returns the correct name", () => {
1612 assertStrictEquals(stringMatch.name, "stringMatch");
1613 });
1614 });
1615 });
1616
1617 describe("stringMatchAll", () => {
1618 it("[[Call]] does the match akin to String::matchAll", () => {
1619 assertEquals(
1620 [...stringMatchAll("very success full", /([sc]+)[ue]?/g)].map((
1621 match,
1622 ) => [...match]),
1623 [["su", "s"], ["cce", "cc"], ["ss", "ss"]],
1624 );
1625 });
1626
1627 it("[[Construct]] throws an error", () => {
1628 assertThrows(() => new stringMatchAll("", /(?:)/g));
1629 });
1630
1631 describe(".length", () => {
1632 it("[[Get]] returns the correct length", () => {
1633 assertStrictEquals(stringMatchAll.length, 2);
1634 });
1635 });
1636
1637 describe(".name", () => {
1638 it("[[Get]] returns the correct name", () => {
1639 assertStrictEquals(stringMatchAll.name, "stringMatchAll");
1640 });
1641 });
1642 });
1643
1644 describe("stringNormalize", () => {
1645 it("[[Call]] normalizes the string properly", () => {
1646 assertStrictEquals(stringNormalize("ẛ", "NFC"), "\u1E9B");
1647 assertStrictEquals(stringNormalize("ẛ", "NFD"), "\u017F\u0307");
1648 assertStrictEquals(stringNormalize("ẛ", "NFKC"), "\u1E61");
1649 assertStrictEquals(stringNormalize("ẛ", "NFKD"), "\u0073\u0307");
1650 });
1651
1652 it("[[Call]] assumes NFC", () => {
1653 assertStrictEquals(stringNormalize("\u017F\u0307"), "\u1E9B");
1654 });
1655
1656 it("[[Call]] throws with an invalid form", () => {
1657 assertThrows(() => stringNormalize("", "NFB"));
1658 });
1659
1660 it("[[Construct]] throws an error", () => {
1661 assertThrows(() => new stringNormalize("", "NFC"));
1662 });
1663
1664 describe(".length", () => {
1665 it("[[Get]] returns the correct length", () => {
1666 assertStrictEquals(stringNormalize.length, 1);
1667 });
1668 });
1669
1670 describe(".name", () => {
1671 it("[[Get]] returns the correct name", () => {
1672 assertStrictEquals(stringNormalize.name, "stringNormalize");
1673 });
1674 });
1675 });
1676
1677 describe("stringPadEnd", () => {
1678 it("[[Call]] pads the end of the string", () => {
1679 assertStrictEquals(stringPadEnd("xx", 3), "xx ");
1680 assertStrictEquals(stringPadEnd("xx", 3, "o"), "xxo");
1681 assertStrictEquals(stringPadEnd("", 3, "xo"), "xox");
1682 assertStrictEquals(stringPadEnd("xx", 3, ""), "xx");
1683 });
1684
1685 it("[[Construct]] throws an error", () => {
1686 assertThrows(() => new stringPadEnd("", 1));
1687 });
1688
1689 describe(".length", () => {
1690 it("[[Get]] returns the correct length", () => {
1691 assertStrictEquals(stringPadEnd.length, 2);
1692 });
1693 });
1694
1695 describe(".name", () => {
1696 it("[[Get]] returns the correct name", () => {
1697 assertStrictEquals(stringPadEnd.name, "stringPadEnd");
1698 });
1699 });
1700 });
1701
1702 describe("stringPadStart", () => {
1703 it("[[Call]] pads the start of the string", () => {
1704 assertStrictEquals(stringPadStart("xx", 3), " xx");
1705 assertStrictEquals(stringPadStart("xx", 3, "o"), "oxx");
1706 assertStrictEquals(stringPadStart("", 3, "xo"), "xox");
1707 assertStrictEquals(stringPadStart("xx", 3, ""), "xx");
1708 });
1709
1710 it("[[Construct]] throws an error", () => {
1711 assertThrows(() => new stringPadStart("", 1));
1712 });
1713
1714 describe(".length", () => {
1715 it("[[Get]] returns the correct length", () => {
1716 assertStrictEquals(stringPadStart.length, 2);
1717 });
1718 });
1719
1720 describe(".name", () => {
1721 it("[[Get]] returns the correct name", () => {
1722 assertStrictEquals(stringPadStart.name, "stringPadStart");
1723 });
1724 });
1725 });
1726
1727 describe("stringRepeat", () => {
1728 it("[[Call]] repeats the string", () => {
1729 assertStrictEquals(stringRepeat("xx", 3), "xxxxxx");
1730 assertStrictEquals(stringRepeat("", 3), "");
1731 assertStrictEquals(stringRepeat("xx", 0), "");
1732 });
1733
1734 it("[[Call]] throws for negative repititions", () => {
1735 assertThrows(() => stringRepeat("", -1));
1736 });
1737
1738 it("[[Call]] throws for infinite repititions", () => {
1739 assertThrows(() => stringRepeat("", Infinity));
1740 });
1741
1742 it("[[Construct]] throws an error", () => {
1743 assertThrows(() => new stringRepeat("", 1));
1744 });
1745
1746 describe(".length", () => {
1747 it("[[Get]] returns the correct length", () => {
1748 assertStrictEquals(stringRepeat.length, 2);
1749 });
1750 });
1751
1752 describe(".name", () => {
1753 it("[[Get]] returns the correct name", () => {
1754 assertStrictEquals(stringRepeat.name, "stringRepeat");
1755 });
1756 });
1757 });
1758
1759 describe("stringReplace", () => {
1760 it("[[Call]] does the replacement akin to String::replace", () => {
1761 assertStrictEquals(
1762 stringReplace("it’s a failure", "failure", "success"),
1763 "it’s a success",
1764 );
1765 assertStrictEquals(
1766 stringReplace(
1767 "very success full",
1768 /([sc]+)[ue]?/,
1769 ($) => $.length,
1770 ),
1771 "very 2ccess full",
1772 );
1773 assertStrictEquals(
1774 stringReplace(
1775 "very success full",
1776 /([sc]+)[ue]?/g,
1777 (...$s) =>
1778 `${$s[0].length}`.repeat($s[1].length)
1779 + $s[0].substring($s[1].length),
1780 ),
1781 "very 2u33e22 full",
1782 );
1783 });
1784
1785 it("[[Construct]] throws an error", () => {
1786 assertThrows(() => new stringReplace("", /(?:)/, ""));
1787 });
1788
1789 describe(".length", () => {
1790 it("[[Get]] returns the correct length", () => {
1791 assertStrictEquals(stringReplace.length, 3);
1792 });
1793 });
1794
1795 describe(".name", () => {
1796 it("[[Get]] returns the correct name", () => {
1797 assertStrictEquals(stringReplace.name, "stringReplace");
1798 });
1799 });
1800 });
1801
1802 describe("stringReplaceAll", () => {
1803 it("[[Call]] does the match akin to String::replaceAll", () => {
1804 assertStrictEquals(
1805 stringReplaceAll("it’s a failure failure", "failure", "success"),
1806 "it’s a success success",
1807 );
1808 assertStrictEquals(
1809 stringReplaceAll(
1810 "very success full",
1811 /([sc]+)[ue]?/g,
1812 (...$s) =>
1813 `${$s[0].length}`.repeat($s[1].length)
1814 + $s[0].substring($s[1].length),
1815 ),
1816 "very 2u33e22 full",
1817 );
1818 });
1819
1820 it("[[Construct]] throws an error", () => {
1821 assertThrows(() => new stringReplaceAll("", /(?:)/g));
1822 });
1823
1824 describe(".length", () => {
1825 it("[[Get]] returns the correct length", () => {
1826 assertStrictEquals(stringReplaceAll.length, 3);
1827 });
1828 });
1829
1830 describe(".name", () => {
1831 it("[[Get]] returns the correct name", () => {
1832 assertStrictEquals(stringReplaceAll.name, "stringReplaceAll");
1833 });
1834 });
1835 });
1836
1837 describe("stringSearch", () => {
1838 it("[[Call]] does the search akin to String::search", () => {
1839 assertStrictEquals(
1840 stringSearch("very success full", /([sc]+)[ue]?/),
1841 5,
1842 );
1843 assertStrictEquals(
1844 stringSearch("very fail full", /([sc]+)[ue]?/),
1845 -1,
1846 );
1847 });
1848
1849 it("[[Construct]] throws an error", () => {
1850 assertThrows(() => new stringSearch("", /(?:)/));
1851 });
1852
1853 describe(".length", () => {
1854 it("[[Get]] returns the correct length", () => {
1855 assertStrictEquals(stringSearch.length, 2);
1856 });
1857 });
1858
1859 describe(".name", () => {
1860 it("[[Get]] returns the correct name", () => {
1861 assertStrictEquals(stringSearch.name, "stringSearch");
1862 });
1863 });
1864 });
1865
1866 describe("stringSlice", () => {
1867 it("[[Call]] slices the string akin to String::search", () => {
1868 assertStrictEquals(
1869 stringSlice("very success full", 5, 12),
1870 "success",
1871 );
1872 assertStrictEquals(
1873 stringSlice("very success full", -12, -5),
1874 "success",
1875 );
1876 });
1877
1878 it("[[Construct]] throws an error", () => {
1879 assertThrows(() => new stringSlice("", 0, 0));
1880 });
1881
1882 describe(".length", () => {
1883 it("[[Get]] returns the correct length", () => {
1884 assertStrictEquals(stringSlice.length, 3);
1885 });
1886 });
1887
1888 describe(".name", () => {
1889 it("[[Get]] returns the correct name", () => {
1890 assertStrictEquals(stringSlice.name, "stringSlice");
1891 });
1892 });
1893 });
1894
1895 describe("stringSplit", () => {
1896 it("[[Call]] splits the string akin to String::split", () => {
1897 assertEquals(stringSplit("success", ""), [
1898 "s",
1899 "u",
1900 "c",
1901 "c",
1902 "e",
1903 "s",
1904 "s",
1905 ]);
1906 assertEquals(stringSplit("success", /(?<=[aeiou])(?=[^aeiou])/), [
1907 "su",
1908 "cce",
1909 "ss",
1910 ]);
1911 assertEquals(stringSplit("success", "failure"), ["success"]);
1912 });
1913
1914 it("[[Call]] recognizes a limit", () => {
1915 assertEquals(stringSplit("success", "", 4), ["s", "u", "c", "c"]);
1916 });
1917
1918 it("[[Construct]] throws an error", () => {
1919 assertThrows(() => new stringSplit("", ""));
1920 });
1921
1922 describe(".length", () => {
1923 it("[[Get]] returns the correct length", () => {
1924 assertStrictEquals(stringSplit.length, 3);
1925 });
1926 });
1927
1928 describe(".name", () => {
1929 it("[[Get]] returns the correct name", () => {
1930 assertStrictEquals(stringSplit.name, "stringSplit");
1931 });
1932 });
1933 });
1934
1935 describe("stringStartsWith", () => {
1936 it("[[Call]] returns whether the string starts with the thing", () => {
1937 assertStrictEquals(
1938 stringStartsWith("success is had", "success "),
1939 true,
1940 );
1941 assertStrictEquals(
1942 stringStartsWith("no success is had", "success "),
1943 false,
1944 );
1945 });
1946
1947 it("[[Call]] accepts an offset", () => {
1948 assertStrictEquals(
1949 stringStartsWith("much success is had", "success ", 5),
1950 true,
1951 );
1952 });
1953
1954 it("[[Call]] returns true for an empty string test", () => {
1955 assertStrictEquals(stringEndsWith("", ""), true);
1956 });
1957
1958 it("[[Construct]] throws an error", () => {
1959 assertThrows(() => new stringStartsWith("", ""));
1960 });
1961
1962 describe(".length", () => {
1963 it("[[Get]] returns the correct length", () => {
1964 assertStrictEquals(stringStartsWith.length, 2);
1965 });
1966 });
1967
1968 describe(".name", () => {
1969 it("[[Get]] returns the correct name", () => {
1970 assertStrictEquals(stringStartsWith.name, "stringStartsWith");
1971 });
1972 });
1973 });
1974
1975 describe("stringStartsWith", () => {
1976 it("[[Call]] returns the string value of a string literal", () => {
1977 assertStrictEquals(stringValue("success"), "success");
1978 });
1979
1980 it("[[Call]] returns the string value of a string object", () => {
1981 const string = new String("success");
1982 Object.defineProperties(string, {
1983 toString: { value: () => "failure" },
1984 valueOf: { value: () => "failure" },
1985 });
1986 assertStrictEquals(stringValue(string), "success");
1987 });
1988
1989 it("[[Call]] throws for non‐strings", () => {
1990 assertThrows(() => stringValue(Object.create(String.prototype)));
1991 });
1992
1993 it("[[Construct]] throws an error", () => {
1994 assertThrows(() => new stringValue(""));
1995 });
1996
1997 describe(".length", () => {
1998 it("[[Get]] returns the correct length", () => {
1999 assertStrictEquals(stringValue.length, 1);
2000 });
2001 });
2002
2003 describe(".name", () => {
2004 it("[[Get]] returns the correct name", () => {
2005 assertStrictEquals(stringValue.name, "stringValue");
2006 });
2007 });
2008 });
2009
2010 describe("stripAndCollapseAsciiWhitespace", () => {
2011 it("[[Call]] collapses mixed inner whitespace", () => {
2012 assertEquals(
2013 stripAndCollapseAsciiWhitespace("🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️"),
2014 "🅰️ 🅱️ 🆎 🅾️",
2015 );
2016 });
2017
2018 it("[[Call]] trims leading and trailing whitespace", () => {
2019 assertStrictEquals(
2020 stripAndCollapseAsciiWhitespace(
2021 "\f\r\n\r\n \n\t\f 🅰️\f \t\n🅱️\r\n\r🆎\n\f🅾️\n\f",
2022 ),
2023 "🅰️ 🅱️ 🆎 🅾️",
2024 );
2025 });
2026
2027 it("[[Call]] returns the empty string for strings of whitespace", () => {
2028 assertStrictEquals(
2029 stripAndCollapseAsciiWhitespace("\f\r\n\r\n \n\t\f \n\f"),
2030 "",
2031 );
2032 });
2033
2034 it("[[Call]] does not collapse other kinds of whitespace", () => {
2035 assertEquals(
2036 stripAndCollapseAsciiWhitespace("a\u202F\u205F\xa0\v\0\bb"),
2037 "a\u202F\u205F\xa0\v\0\bb",
2038 );
2039 });
2040
2041 it("[[Construct]] throws an error", () => {
2042 assertThrows(() => new stripAndCollapseAsciiWhitespace(""));
2043 });
2044
2045 describe(".length", () => {
2046 it("[[Get]] returns the correct length", () => {
2047 assertStrictEquals(stripAndCollapseAsciiWhitespace.length, 1);
2048 });
2049 });
2050
2051 describe(".name", () => {
2052 it("[[Get]] returns the correct name", () => {
2053 assertStrictEquals(
2054 stripAndCollapseAsciiWhitespace.name,
2055 "stripAndCollapseAsciiWhitespace",
2056 );
2057 });
2058 });
2059 });
2060
2061 describe("stripLeadingAndTrailingAsciiWhitespace", () => {
2062 it("[[Call]] trims leading and trailing whitespace", () => {
2063 assertStrictEquals(
2064 stripLeadingAndTrailingAsciiWhitespace(
2065 "\f\r\n\r\n \n\t\f 🅰️🅱️🆎🅾️\n\f",
2066 ),
2067 "🅰️🅱️🆎🅾️",
2068 );
2069 });
2070
2071 it("[[Call]] returns the empty string for strings of whitespace", () => {
2072 assertStrictEquals(
2073 stripLeadingAndTrailingAsciiWhitespace("\f\r\n\r\n \n\t\f \n\f"),
2074 "",
2075 );
2076 });
2077
2078 it("[[Call]] does not trim other kinds of whitespace", () => {
2079 assertEquals(
2080 stripLeadingAndTrailingAsciiWhitespace(
2081 "\v\u202F\u205Fx\0\b\xa0",
2082 ),
2083 "\v\u202F\u205Fx\0\b\xa0",
2084 );
2085 });
2086
2087 it("[[Call]] does not adjust inner whitespace", () => {
2088 assertEquals(
2089 stripLeadingAndTrailingAsciiWhitespace("a b"),
2090 "a b",
2091 );
2092 });
2093
2094 it("[[Construct]] throws an error", () => {
2095 assertThrows(() => new stripLeadingAndTrailingAsciiWhitespace(""));
2096 });
2097
2098 describe(".length", () => {
2099 it("[[Get]] returns the correct length", () => {
2100 assertStrictEquals(
2101 stripLeadingAndTrailingAsciiWhitespace.length,
2102 1,
2103 );
2104 });
2105 });
2106
2107 describe(".name", () => {
2108 it("[[Get]] returns the correct name", () => {
2109 assertStrictEquals(
2110 stripLeadingAndTrailingAsciiWhitespace.name,
2111 "stripLeadingAndTrailingAsciiWhitespace",
2112 );
2113 });
2114 });
2115 });
2116
2117 describe("substring", () => {
2118 it("[[Call]] returns the substring", () => {
2119 assertStrictEquals(
2120 substring("success", 0),
2121 "success",
2122 );
2123 assertStrictEquals(
2124 substring("very success full", 5, 12),
2125 "success",
2126 );
2127 });
2128
2129 it("[[Construct]] throws an error", () => {
2130 assertThrows(() => new substring("", 0));
2131 });
2132
2133 describe(".length", () => {
2134 it("[[Get]] returns the correct length", () => {
2135 assertStrictEquals(substring.length, 3);
2136 });
2137 });
2138
2139 describe(".name", () => {
2140 it("[[Get]] returns the correct name", () => {
2141 assertStrictEquals(substring.name, "substring");
2142 });
2143 });
2144 });
2145
2146 describe("toScalarValueString", () => {
2147 it("[[Call]] replaces invalid values", () => {
2148 assertStrictEquals(
2149 toScalarValueString("Ii🎙\uDFFF\uDD96\uD83C\uD800🆗☺"),
2150 "Ii🎙\uFFFD\uFFFD\uFFFD\uFFFD🆗☺",
2151 );
2152 });
2153
2154 it("[[Construct]] throws an error", () => {
2155 assertThrows(() => new toScalarValueString(""));
2156 });
2157
2158 describe(".length", () => {
2159 it("[[Get]] returns the correct length", () => {
2160 assertStrictEquals(toScalarValueString.length, 1);
2161 });
2162 });
2163
2164 describe(".name", () => {
2165 it("[[Get]] returns the correct name", () => {
2166 assertStrictEquals(
2167 toScalarValueString.name,
2168 "toScalarValueString",
2169 );
2170 });
2171 });
2172 });
2173
2174 describe("toString", () => {
2175 it("[[Call]] converts to a string", () => {
2176 assertStrictEquals(
2177 toString({
2178 toString() {
2179 return "success";
2180 },
2181 }),
2182 "success",
2183 );
2184 });
2185
2186 it("[[Call]] throws when provided a symbol", () => {
2187 assertThrows(() => toString(Symbol()));
2188 });
2189
2190 it("[[Construct]] throws an error", () => {
2191 assertThrows(() => new toString(""));
2192 });
2193
2194 describe(".length", () => {
2195 it("[[Get]] returns the correct length", () => {
2196 assertStrictEquals(toString.length, 1);
2197 });
2198 });
2199
2200 describe(".name", () => {
2201 it("[[Get]] returns the correct name", () => {
2202 assertStrictEquals(toString.name, "toString");
2203 });
2204 });
2205 });
This page took 1.565596 seconds and 5 git commands to generate.