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