]> Lady’s Gitweb - Pisces/blob - value.test.js
babd59d9a449972170a6d3d6b673f557826d72d0
[Pisces] / value.test.js
1 // ♓🌟 Piscēs ∷ value.test.js
2 // ====================================================================
3 //
4 // Copyright © 2022–2023 Lady [@ Lady’s Computer].
5 //
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
9
10 import {
11 assertStrictEquals,
12 assertThrows,
13 describe,
14 it,
15 } from "./dev-deps.js";
16 import {
17 ASYNC_ITERATOR,
18 canonicalNumericIndexString,
19 HAS_INSTANCE,
20 IS_CONCAT_SPREADABLE,
21 isIntegerIndexString,
22 ITERATOR,
23 lengthOfArraylike,
24 MATCH,
25 MATCH_ALL,
26 NULL,
27 ordinaryToPrimitive,
28 REPLACE,
29 sameValue,
30 sameValueZero,
31 SPECIES,
32 SPLIT,
33 TO_PRIMITIVE,
34 TO_STRING_TAG,
35 toIndex,
36 toLength,
37 toPrimitive,
38 type,
39 UNDEFINED,
40 UNSCOPABLES,
41 } from "./value.js";
42
43 describe("ASYNC_ITERATOR", () => {
44 it("[[Get]] is @@asyncIterator", () => {
45 assertStrictEquals(ASYNC_ITERATOR, Symbol.asyncIterator);
46 });
47 });
48
49 describe("HAS_INSTANCE", () => {
50 it("[[Get]] is @@hasInstance", () => {
51 assertStrictEquals(HAS_INSTANCE, Symbol.hasInstance);
52 });
53 });
54
55 describe("IS_CONCAT_SPREADABLE", () => {
56 it("[[Get]] is @@isConcatSpreadable", () => {
57 assertStrictEquals(
58 IS_CONCAT_SPREADABLE,
59 Symbol.isConcatSpreadable,
60 );
61 });
62 });
63
64 describe("ITERATOR", () => {
65 it("[[Get]] is @@iterator", () => {
66 assertStrictEquals(ITERATOR, Symbol.iterator);
67 });
68 });
69
70 describe("MATCH", () => {
71 it("[[Get]] is @@match", () => {
72 assertStrictEquals(MATCH, Symbol.match);
73 });
74 });
75
76 describe("MATCH_ALL", () => {
77 it("[[Get]] is @@matchAll", () => {
78 assertStrictEquals(MATCH_ALL, Symbol.matchAll);
79 });
80 });
81
82 describe("NULL", () => {
83 it("[[Get]] is null", () => {
84 assertStrictEquals(NULL, null);
85 });
86 });
87
88 describe("REPLACE", () => {
89 it("[[Get]] is @@replace", () => {
90 assertStrictEquals(REPLACE, Symbol.replace);
91 });
92 });
93
94 describe("SPECIES", () => {
95 it("[[Get]] is @@species", () => {
96 assertStrictEquals(SPECIES, Symbol.species);
97 });
98 });
99
100 describe("SPLIT", () => {
101 it("[[Get]] is @@split", () => {
102 assertStrictEquals(SPLIT, Symbol.split);
103 });
104 });
105
106 describe("TO_PRIMITIVE", () => {
107 it("[[Get]] is @@toPrimitive", () => {
108 assertStrictEquals(TO_PRIMITIVE, Symbol.toPrimitive);
109 });
110 });
111
112 describe("TO_STRING_TAG", () => {
113 it("[[Get]] is @@toStringTag", () => {
114 assertStrictEquals(TO_STRING_TAG, Symbol.toStringTag);
115 });
116 });
117
118 describe("UNDEFINED", () => {
119 it("[[Get]] is undefined", () => {
120 assertStrictEquals(UNDEFINED, void {});
121 });
122 });
123
124 describe("UNSCOPABLES", () => {
125 it("[[Get]] is @@unscopables", () => {
126 assertStrictEquals(UNSCOPABLES, Symbol.unscopables);
127 });
128 });
129
130 describe("canonicalNumericIndexString", () => {
131 it("[[Call]] returns undefined for nonstrings", () => {
132 assertStrictEquals(canonicalNumericIndexString(1), void {});
133 });
134
135 it("[[Call]] returns undefined for noncanonical strings", () => {
136 assertStrictEquals(canonicalNumericIndexString(""), void {});
137 assertStrictEquals(canonicalNumericIndexString("01"), void {});
138 assertStrictEquals(
139 canonicalNumericIndexString("9007199254740993"),
140 void {},
141 );
142 });
143
144 it('[[Call]] returns -0 for "-0"', () => {
145 assertStrictEquals(canonicalNumericIndexString("-0"), -0);
146 });
147
148 it("[[Call]] returns the corresponding number for canonical strings", () => {
149 assertStrictEquals(canonicalNumericIndexString("0"), 0);
150 assertStrictEquals(canonicalNumericIndexString("-0.25"), -0.25);
151 assertStrictEquals(
152 canonicalNumericIndexString("9007199254740992"),
153 9007199254740992,
154 );
155 assertStrictEquals(canonicalNumericIndexString("NaN"), 0 / 0);
156 assertStrictEquals(canonicalNumericIndexString("Infinity"), 1 / 0);
157 assertStrictEquals(
158 canonicalNumericIndexString("-Infinity"),
159 -1 / 0,
160 );
161 });
162
163 it("[[Construct]] throws an error", () => {
164 assertThrows(() => new canonicalNumericIndexString(""));
165 });
166
167 describe(".length", () => {
168 it("[[Get]] returns the correct length", () => {
169 assertStrictEquals(canonicalNumericIndexString.length, 1);
170 });
171 });
172
173 describe(".name", () => {
174 it("[[Get]] returns the correct name", () => {
175 assertStrictEquals(
176 canonicalNumericIndexString.name,
177 "canonicalNumericIndexString",
178 );
179 });
180 });
181 });
182
183 describe("isIntegerIndexString", () => {
184 it("[[Call]] returns false for nonstrings", () => {
185 assertStrictEquals(isIntegerIndexString(1), false);
186 });
187
188 it("[[Call]] returns false for noncanonical strings", () => {
189 assertStrictEquals(isIntegerIndexString(""), false);
190 assertStrictEquals(isIntegerIndexString("01"), false);
191 assertStrictEquals(
192 isIntegerIndexString("9007199254740993"),
193 false,
194 );
195 });
196
197 it("[[Call]] returns false for nonfinite numbers", () => {
198 assertStrictEquals(isIntegerIndexString("NaN"), false);
199 assertStrictEquals(isIntegerIndexString("Infinity"), false);
200 assertStrictEquals(isIntegerIndexString("-Infinity"), false);
201 });
202
203 it("[[Call]] returns false for negative numbers", () => {
204 assertStrictEquals(isIntegerIndexString("-0"), false);
205 assertStrictEquals(isIntegerIndexString("-1"), false);
206 });
207
208 it("[[Call]] returns false for nonintegers", () => {
209 assertStrictEquals(isIntegerIndexString("0.25"), false);
210 assertStrictEquals(isIntegerIndexString("1.1"), false);
211 });
212
213 it("[[Call]] returns false for numbers greater than or equal to 2 ** 53", () => {
214 assertStrictEquals(
215 isIntegerIndexString("9007199254740992"),
216 false,
217 );
218 });
219
220 it("[[Call]] returns true for safe canonical integer strings", () => {
221 assertStrictEquals(isIntegerIndexString("0"), true);
222 assertStrictEquals(isIntegerIndexString("9007199254740991"), true);
223 });
224 });
225
226 describe("lengthOfArraylike", () => {
227 it("[[Call]] returns the length", () => {
228 assertStrictEquals(
229 lengthOfArraylike({ length: 9007199254740991 }),
230 9007199254740991,
231 );
232 });
233
234 it("[[Call]] returns a non·nan result", () => {
235 assertStrictEquals(lengthOfArraylike({ length: NaN }), 0);
236 assertStrictEquals(lengthOfArraylike({ length: "failure" }), 0);
237 });
238
239 it("[[Call]] returns an integral result", () => {
240 assertStrictEquals(lengthOfArraylike({ length: 0.25 }), 0);
241 assertStrictEquals(lengthOfArraylike({ length: 1.1 }), 1);
242 });
243
244 it("[[Call]] returns a result greater than or equal to zero", () => {
245 assertStrictEquals(lengthOfArraylike({ length: -0 }), 0);
246 assertStrictEquals(lengthOfArraylike({ length: -1 }), 0);
247 assertStrictEquals(lengthOfArraylike({ length: -Infinity }), 0);
248 });
249
250 it("[[Call]] returns a result less than 2 ** 53", () => {
251 assertStrictEquals(
252 lengthOfArraylike({ length: 9007199254740992 }),
253 9007199254740991,
254 );
255 assertStrictEquals(
256 lengthOfArraylike({ length: Infinity }),
257 9007199254740991,
258 );
259 });
260
261 it("[[Call]] does not require an object argument", () => {
262 assertStrictEquals(lengthOfArraylike("string"), 6);
263 assertStrictEquals(lengthOfArraylike(Symbol()), 0);
264 });
265
266 it("[[Construct]] throws an error", () => {
267 assertThrows(() => new lengthOfArraylike(""));
268 });
269
270 describe(".length", () => {
271 it("[[Get]] returns the correct length", () => {
272 assertStrictEquals(lengthOfArraylike.length, 1);
273 });
274 });
275
276 describe(".name", () => {
277 it("[[Get]] returns the correct name", () => {
278 assertStrictEquals(lengthOfArraylike.name, "lengthOfArraylike");
279 });
280 });
281 });
282
283 describe("ordinaryToPrimitive", () => {
284 it("[[Call]] prefers `valueOf` by default", () => {
285 const obj = {
286 toString() {
287 return "failure";
288 },
289 valueOf() {
290 return "success";
291 },
292 };
293 assertStrictEquals(ordinaryToPrimitive(obj), "success");
294 assertStrictEquals(ordinaryToPrimitive(obj, "default"), "success");
295 });
296
297 it('[[Call]] prefers `valueOf` for a "number" hint', () => {
298 const obj = {
299 toString() {
300 return "failure";
301 },
302 valueOf() {
303 return "success";
304 },
305 };
306 assertStrictEquals(ordinaryToPrimitive(obj, "number"), "success");
307 });
308
309 it('[[Call]] prefers `toString` for a "string" hint', () => {
310 const obj = {
311 toString() {
312 return "success";
313 },
314 valueOf() {
315 return "failure";
316 },
317 };
318 assertStrictEquals(ordinaryToPrimitive(obj, "string"), "success");
319 });
320
321 it("[[Call]] falls back to the other method if the first isn’t callable", () => {
322 const obj = {
323 toString() {
324 return "success";
325 },
326 valueOf: "failure",
327 };
328 assertStrictEquals(ordinaryToPrimitive(obj), "success");
329 });
330
331 it("[[Call]] falls back to the other method if the first returns an object", () => {
332 const obj = {
333 toString() {
334 return "success";
335 },
336 valueOf() {
337 return new String("failure");
338 },
339 };
340 assertStrictEquals(ordinaryToPrimitive(obj), "success");
341 });
342
343 it("[[Call]] throws an error if neither method is callable", () => {
344 const obj = {
345 toString: "failure",
346 valueOf: "failure",
347 };
348 assertThrows(() => ordinaryToPrimitive(obj));
349 });
350
351 it("[[Call]] throws an error if neither method returns an object", () => {
352 const obj = {
353 toString() {
354 return new String("failure");
355 },
356 valueOf() {
357 return new String("failure");
358 },
359 };
360 assertThrows(() => ordinaryToPrimitive(obj));
361 });
362
363 it("[[Construct]] throws an error", () => {
364 assertThrows(() => new ordinaryToPrimitive(""));
365 });
366
367 describe(".length", () => {
368 it("[[Get]] returns the correct length", () => {
369 assertStrictEquals(ordinaryToPrimitive.length, 2);
370 });
371 });
372
373 describe(".name", () => {
374 it("[[Get]] returns the correct name", () => {
375 assertStrictEquals(
376 ordinaryToPrimitive.name,
377 "ordinaryToPrimitive",
378 );
379 });
380 });
381 });
382
383 describe("sameValue", () => {
384 it("[[Call]] returns false for null 🆚 undefined", () => {
385 assertStrictEquals(sameValue(null, undefined), false);
386 });
387
388 it("[[Call]] returns false for null 🆚 an object", () => {
389 assertStrictEquals(sameValue(null, {}), false);
390 });
391
392 it("[[Call]] returns true for null 🆚 null", () => {
393 assertStrictEquals(sameValue(null, null), true);
394 });
395
396 it("[[Call]] returns false for two different objects", () => {
397 assertStrictEquals(sameValue({}, {}), false);
398 });
399
400 it("[[Call]] returns true for the same object", () => {
401 const obj = {};
402 assertStrictEquals(sameValue(obj, obj), true);
403 });
404
405 it("[[Call]] returns false for ±0", () => {
406 assertStrictEquals(sameValue(0, -0), false);
407 });
408
409 it("[[Call]] returns true for -0", () => {
410 assertStrictEquals(sameValue(-0, -0), true);
411 });
412
413 it("[[Call]] returns true for nan", () => {
414 assertStrictEquals(sameValue(0 / 0, 0 / 0), true);
415 });
416
417 it("[[Call]] returns false for a primitive and its wrapped object", () => {
418 assertStrictEquals(sameValue(false, new Boolean(false)), false);
419 });
420
421 it("[[Construct]] throws an error", () => {
422 assertThrows(() => new sameValue(true, true));
423 });
424
425 describe(".length", () => {
426 it("[[Get]] returns the correct length", () => {
427 assertStrictEquals(sameValue.length, 2);
428 });
429 });
430
431 describe(".name", () => {
432 it("[[Get]] returns the correct name", () => {
433 assertStrictEquals(sameValue.name, "sameValue");
434 });
435 });
436 });
437
438 describe("sameValueZero", () => {
439 it("[[Call]] returns false for null 🆚 undefined", () => {
440 assertStrictEquals(sameValueZero(null, undefined), false);
441 });
442
443 it("[[Call]] returns false for null 🆚 an object", () => {
444 assertStrictEquals(sameValueZero(null, {}), false);
445 });
446
447 it("[[Call]] returns true for null 🆚 null", () => {
448 assertStrictEquals(sameValueZero(null, null), true);
449 });
450
451 it("[[Call]] returns false for two different objects", () => {
452 assertStrictEquals(sameValueZero({}, {}), false);
453 });
454
455 it("[[Call]] returns true for the same object", () => {
456 const obj = {};
457 assertStrictEquals(sameValueZero(obj, obj), true);
458 });
459
460 it("[[Call]] returns true for ±0", () => {
461 assertStrictEquals(sameValueZero(0, -0), true);
462 });
463
464 it("[[Call]] returns true for -0", () => {
465 assertStrictEquals(sameValueZero(-0, -0), true);
466 });
467
468 it("[[Call]] returns true for nan", () => {
469 assertStrictEquals(sameValueZero(0 / 0, 0 / 0), true);
470 });
471
472 it("[[Call]] returns false for a primitive and its wrapped object", () => {
473 assertStrictEquals(
474 sameValueZero(false, new Boolean(false)),
475 false,
476 );
477 });
478
479 it("[[Construct]] throws an error", () => {
480 assertThrows(() => new sameValueZero(true, true));
481 });
482
483 describe(".length", () => {
484 it("[[Get]] returns the correct length", () => {
485 assertStrictEquals(sameValueZero.length, 2);
486 });
487 });
488
489 describe(".name", () => {
490 it("[[Get]] returns the correct name", () => {
491 assertStrictEquals(sameValueZero.name, "sameValueZero");
492 });
493 });
494 });
495
496 describe("toIndex", () => {
497 it("[[Call]] returns an index", () => {
498 assertStrictEquals(toIndex(9007199254740991), 9007199254740991);
499 });
500
501 it("[[Call]] returns zero for a zerolike argument", () => {
502 assertStrictEquals(toIndex(NaN), 0);
503 assertStrictEquals(toIndex("failure"), 0);
504 assertStrictEquals(toIndex(-0), 0);
505 });
506
507 it("[[Call]] rounds down to the nearest integer", () => {
508 assertStrictEquals(toIndex(0.25), 0);
509 assertStrictEquals(toIndex(1.1), 1);
510 });
511
512 it("[[Call]] throws when provided a negative number", () => {
513 assertThrows(() => toIndex(-1));
514 assertThrows(() => toIndex(-Infinity));
515 });
516
517 it("[[Call]] throws when provided a number greater than or equal to 2 ** 53", () => {
518 assertThrows(() => toIndex(9007199254740992));
519 assertThrows(() => toIndex(Infinity));
520 });
521
522 it("[[Construct]] throws an error", () => {
523 assertThrows(() => new toIndex(0));
524 });
525
526 describe(".length", () => {
527 it("[[Get]] returns the correct length", () => {
528 assertStrictEquals(toIndex.length, 1);
529 });
530 });
531
532 describe(".name", () => {
533 it("[[Get]] returns the correct name", () => {
534 assertStrictEquals(toIndex.name, "toIndex");
535 });
536 });
537 });
538
539 describe("toLength", () => {
540 it("[[Call]] returns a length", () => {
541 assertStrictEquals(toLength(9007199254740991), 9007199254740991);
542 });
543
544 it("[[Call]] returns zero for a nan argument", () => {
545 assertStrictEquals(toLength(NaN), 0);
546 assertStrictEquals(toLength("failure"), 0);
547 });
548
549 it("[[Call]] rounds down to the nearest integer", () => {
550 assertStrictEquals(toLength(0.25), 0);
551 assertStrictEquals(toLength(1.1), 1);
552 });
553
554 it("[[Call]] returns a result greater than or equal to zero", () => {
555 assertStrictEquals(toLength(-0), 0);
556 assertStrictEquals(toLength(-1), 0);
557 assertStrictEquals(toLength(-Infinity), 0);
558 });
559
560 it("[[Call]] returns a result less than 2 ** 53", () => {
561 assertStrictEquals(toLength(9007199254740992), 9007199254740991);
562 assertStrictEquals(toLength(Infinity), 9007199254740991);
563 });
564
565 it("[[Construct]] throws an error", () => {
566 assertThrows(() => new toLength(0));
567 });
568
569 describe(".length", () => {
570 it("[[Get]] returns the correct length", () => {
571 assertStrictEquals(toLength.length, 1);
572 });
573 });
574
575 describe(".name", () => {
576 it("[[Get]] returns the correct name", () => {
577 assertStrictEquals(toLength.name, "toLength");
578 });
579 });
580 });
581
582 describe("toPrimitive", () => {
583 it("[[Call]] returns the argument when passed a primitive", () => {
584 const value = Symbol();
585 assertStrictEquals(toPrimitive(value), value);
586 });
587
588 it("[[Call]] works with nullish values", () => {
589 assertStrictEquals(toPrimitive(null), null);
590 assertStrictEquals(toPrimitive(), void {});
591 });
592
593 it("[[Call]] calls ordinaryToPrimitive by default", () => {
594 const value = Object.assign(
595 Object.create(null),
596 {
597 valueOf() {
598 return "success";
599 },
600 },
601 );
602 assertStrictEquals(toPrimitive(value), "success");
603 });
604
605 it("[[Call]] accepts a hint", () => {
606 const value = Object.assign(
607 Object.create(null),
608 {
609 toString() {
610 return "success";
611 },
612 valueOf() {
613 return "failure";
614 },
615 },
616 );
617 assertStrictEquals(toPrimitive(value, "string"), "success");
618 });
619
620 it("[[Call]] uses the exotic toPrimitive method if available", () => {
621 const value = Object.assign(
622 Object.create(null),
623 {
624 [Symbol.toPrimitive]() {
625 return "success";
626 },
627 },
628 );
629 assertStrictEquals(toPrimitive(value), "success");
630 });
631
632 it("[[Call]] passes the hint to the exotic toPrimitive", () => {
633 const value = Object.assign(
634 Object.create(null),
635 {
636 [Symbol.toPrimitive](hint) {
637 return hint === "string" ? "success" : "failure";
638 },
639 },
640 );
641 assertStrictEquals(toPrimitive(value, "string"), "success");
642 });
643
644 it('[[Call]] passes a "default" hint by default', () => {
645 const value = Object.assign(
646 Object.create(null),
647 {
648 [Symbol.toPrimitive](hint) {
649 return hint === "default" ? "success" : "failure";
650 },
651 },
652 );
653 assertStrictEquals(toPrimitive(value), "success");
654 });
655
656 it("[[Call]] throws for an invalid hint", () => {
657 const value1 = Object.assign(
658 Object.create(null),
659 {
660 [Symbol.toPrimitive]() {
661 return "success";
662 },
663 },
664 );
665 const value2 = Object.assign(
666 Object.create(null),
667 {
668 valueOf() {
669 return true;
670 },
671 },
672 );
673 assertThrows(() => toPrimitive(value1, "badhint"));
674 assertThrows(() => toPrimitive(value2, "badhint"));
675 assertThrows(() => toPrimitive(true, "badhint"));
676 });
677
678 it("[[Construct]] throws an error", () => {
679 assertThrows(() => new toPrimitive(true));
680 });
681
682 describe(".length", () => {
683 it("[[Get]] returns the correct length", () => {
684 assertStrictEquals(toPrimitive.length, 1);
685 });
686 });
687
688 describe(".name", () => {
689 it("[[Get]] returns the correct name", () => {
690 assertStrictEquals(toPrimitive.name, "toPrimitive");
691 });
692 });
693 });
694
695 describe("type", () => {
696 it('[[Call]] returns "null" for null', () => {
697 assertStrictEquals(type(null), "null");
698 });
699
700 it('[[Call]] returns "undefined" for undefined', () => {
701 assertStrictEquals(type(void {}), "undefined");
702 });
703
704 it('[[Call]] returns "object" for non‐callable objects', () => {
705 assertStrictEquals(type(Object.create(null)), "object");
706 });
707
708 it('[[Call]] returns "object" for callable objects', () => {
709 assertStrictEquals(type(() => {}), "object");
710 });
711
712 it('[[Call]] returns "object" for constructable objects', () => {
713 assertStrictEquals(type(class {}), "object");
714 });
715
716 it("[[Construct]] throws an error", () => {
717 assertThrows(() => new type({}));
718 });
719
720 describe(".length", () => {
721 it("[[Get]] returns the correct length", () => {
722 assertStrictEquals(type.length, 1);
723 });
724 });
725
726 describe(".name", () => {
727 it("[[Get]] returns the correct name", () => {
728 assertStrictEquals(type.name, "type");
729 });
730 });
731 });
This page took 0.181334 seconds and 3 git commands to generate.