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