X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/da52ccecff0e48d48ea235b4d0def93b149eb0c1..refs/heads/current:/value.test.js?ds=sidebyside diff --git a/value.test.js b/value.test.js index df86778..ce6464d 100644 --- a/value.test.js +++ b/value.test.js @@ -8,7 +8,7 @@ // file, You can obtain one at . import { - assert, + assertEquals, assertStrictEquals, assertThrows, describe, @@ -16,24 +16,51 @@ import { } from "./dev-deps.js"; import { ASYNC_ITERATOR, + completePropertyDescriptor, HAS_INSTANCE, IS_CONCAT_SPREADABLE, + isAccessorDescriptor, + isDataDescriptor, + isFullyPopulatedDescriptor, + isGenericDescriptor, ITERATOR, + LN10, + LN2, + LOG10ℇ, + LOG2ℇ, MATCH, MATCH_ALL, + MAXIMUM_NUMBER, + MAXIMUM_SAFE_INTEGRAL_NUMBER, + MINIMUM_NUMBER, + MINIMUM_SAFE_INTEGRAL_NUMBER, + NAN, + NEGATIVE_INFINITY, + NEGATIVE_ZERO, NULL, ordinaryToPrimitive, + POSITIVE_INFINITY, + POSITIVE_ZERO, + RECIPROCAL_SQRT2, REPLACE, sameValue, sameValueZero, SPECIES, SPLIT, + SQRT2, TO_PRIMITIVE, TO_STRING_TAG, + toFunctionName, + toIndex, + toLength, toPrimitive, + toPropertyKey, type, UNDEFINED, UNSCOPABLES, + Ε, + Π, + ℇ, } from "./value.js"; describe("ASYNC_ITERATOR", () => { @@ -63,6 +90,30 @@ describe("ITERATOR", () => { }); }); +describe("LN10", () => { + it("[[Get]] is ln(10)", () => { + assertStrictEquals(LN10, Math.LN10); + }); +}); + +describe("LN2", () => { + it("[[Get]] is ln(2)", () => { + assertStrictEquals(LN2, Math.LN2); + }); +}); + +describe("LOG10ℇ", () => { + it("[[Get]] is log10(ℇ)", () => { + assertStrictEquals(LOG10ℇ, Math.LOG10E); + }); +}); + +describe("LOG2ℇ", () => { + it("[[Get]] is log2(ℇ)", () => { + assertStrictEquals(LOG2ℇ, Math.LOG2E); + }); +}); + describe("MATCH", () => { it("[[Get]] is @@match", () => { assertStrictEquals(MATCH, Symbol.match); @@ -75,12 +126,78 @@ describe("MATCH_ALL", () => { }); }); +describe("MAXIMUM_NUMBER", () => { + it("[[Get]] is the maximum number", () => { + assertStrictEquals(MAXIMUM_NUMBER, Number.MAX_VALUE); + }); +}); + +describe("MAXIMUM_SAFE_INTEGRAL_NUMBER", () => { + it("[[Get]] is the maximum safe integral number", () => { + assertStrictEquals( + MAXIMUM_SAFE_INTEGRAL_NUMBER, + Number.MAX_SAFE_INTEGER, + ); + }); +}); + +describe("MINIMUM_NUMBER", () => { + it("[[Get]] is the minimum number", () => { + assertStrictEquals(MINIMUM_NUMBER, Number.MIN_VALUE); + }); +}); + +describe("MINIMUM_SAFE_INTEGRAL_NUMBER", () => { + it("[[Get]] is the minimum safe integral number", () => { + assertStrictEquals( + MINIMUM_SAFE_INTEGRAL_NUMBER, + Number.MIN_SAFE_INTEGER, + ); + }); +}); + +describe("NAN", () => { + it("[[Get]] is nan", () => { + assertStrictEquals(NAN, NaN); + }); +}); + +describe("NEGATIVE_INFINITY", () => { + it("[[Get]] is negative infinity", () => { + assertStrictEquals(NEGATIVE_INFINITY, -Infinity); + }); +}); + +describe("NEGATIVE_ZERO", () => { + it("[[Get]] is negative zero", () => { + assertStrictEquals(NEGATIVE_ZERO, -0); + }); +}); + describe("NULL", () => { it("[[Get]] is null", () => { assertStrictEquals(NULL, null); }); }); +describe("POSITIVE_INFINITY", () => { + it("[[Get]] is negative infinity", () => { + assertStrictEquals(POSITIVE_INFINITY, Infinity); + }); +}); + +describe("POSITIVE_ZERO", () => { + it("[[Get]] is positive zero", () => { + assertStrictEquals(POSITIVE_ZERO, 0); + }); +}); + +describe("RECIPROCAL_SQRT2", () => { + it("[[Get]] is sqrt(½)", () => { + assertStrictEquals(RECIPROCAL_SQRT2, Math.SQRT1_2); + }); +}); + describe("REPLACE", () => { it("[[Get]] is @@replace", () => { assertStrictEquals(REPLACE, Symbol.replace); @@ -99,6 +216,12 @@ describe("SPLIT", () => { }); }); +describe("SQRT2", () => { + it("[[Get]] is sqrt(2)", () => { + assertStrictEquals(SQRT2, Math.SQRT2); + }); +}); + describe("TO_PRIMITIVE", () => { it("[[Get]] is @@toPrimitive", () => { assertStrictEquals(TO_PRIMITIVE, Symbol.toPrimitive); @@ -123,6 +246,262 @@ describe("UNSCOPABLES", () => { }); }); +describe("completePropertyDescriptor", () => { + it("[[Call]] completes a generic descriptor", () => { + const desc = {}; + completePropertyDescriptor(desc); + assertEquals(desc, { + configurable: false, + enumerable: false, + value: undefined, + writable: false, + }); + }); + + it("[[Call]] completes a data descriptor", () => { + const desc = { value: undefined }; + completePropertyDescriptor(desc); + assertEquals(desc, { + configurable: false, + enumerable: false, + value: undefined, + writable: false, + }); + }); + + it("[[Call]] completes an accessor descriptor", () => { + const desc = { get: undefined }; + completePropertyDescriptor(desc); + assertEquals(desc, { + configurable: false, + enumerable: false, + get: undefined, + set: undefined, + }); + }); + + it("[[Call]] throws an error when the descriptor is undefined", () => { + assertThrows(() => new completePropertyDescriptor(undefined)); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new completePropertyDescriptor({})); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(completePropertyDescriptor.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + completePropertyDescriptor.name, + "completePropertyDescriptor", + ); + }); + }); +}); + +describe("isAccessorDescriptor", () => { + it("[[Call]] returns false for a generic descriptor", () => { + assertStrictEquals(isAccessorDescriptor({}), false); + }); + + it("[[Get]] returns false for a data descriptor", () => { + assertStrictEquals( + isAccessorDescriptor({ value: undefined }), + false, + ); + assertStrictEquals( + isAccessorDescriptor({ writable: undefined }), + false, + ); + }); + + it("[[Get]] returns true for an accessor descriptor", () => { + assertStrictEquals(isAccessorDescriptor({ get: undefined }), true); + assertStrictEquals(isAccessorDescriptor({ set: undefined }), true); + }); + + it("[[Get]] returns false for undefined", () => { + assertStrictEquals(isAccessorDescriptor(undefined), false); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new isAccessorDescriptor({})); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(isAccessorDescriptor.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + isAccessorDescriptor.name, + "isAccessorDescriptor", + ); + }); + }); +}); + +describe("isDataDescriptor", () => { + it("[[Call]] returns false for a generic descriptor", () => { + assertStrictEquals(isDataDescriptor({}), false); + }); + + it("[[Get]] returns true for a data descriptor", () => { + assertStrictEquals(isDataDescriptor({ value: undefined }), true); + assertStrictEquals(isDataDescriptor({ writable: true }), true); + }); + + it("[[Get]] returns false for an accessor descriptor", () => { + assertStrictEquals(isDataDescriptor({ get: undefined }), false); + assertStrictEquals(isDataDescriptor({ set: undefined }), false); + }); + + it("[[Get]] returns false for undefined", () => { + assertStrictEquals(isDataDescriptor(undefined), false); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new isDataDescriptor({})); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(isDataDescriptor.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals(isDataDescriptor.name, "isDataDescriptor"); + }); + }); +}); + +describe("isFullyPopulatedDescriptor", () => { + it("[[Call]] returns false for a generic descriptor", () => { + assertStrictEquals(isFullyPopulatedDescriptor({}), false); + }); + + it("[[Get]] returns false for a non‐fully‐populated data descriptor", () => { + assertStrictEquals( + isFullyPopulatedDescriptor({ value: undefined }), + false, + ); + assertStrictEquals( + isFullyPopulatedDescriptor({ writable: true }), + false, + ); + }); + + it("[[Get]] returns true for a fully‐populated data descriptor", () => { + assertStrictEquals( + isFullyPopulatedDescriptor({ + configurable: true, + enumerable: true, + value: undefined, + writable: true, + }), + true, + ); + }); + + it("[[Get]] returns false for a non‐fully‐populated accessor descriptor", () => { + assertStrictEquals( + isFullyPopulatedDescriptor({ get: undefined }), + false, + ); + assertStrictEquals( + isFullyPopulatedDescriptor({ set: undefined }), + false, + ); + }); + + it("[[Get]] returns true for a fully‐populated accessor descriptor", () => { + assertStrictEquals( + isFullyPopulatedDescriptor({ + configurable: true, + enumerable: true, + get: undefined, + set: undefined, + }), + true, + ); + }); + + it("[[Get]] returns false for undefined", () => { + assertStrictEquals(isFullyPopulatedDescriptor(undefined), false); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new isFullyPopulatedDescriptor({})); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(isFullyPopulatedDescriptor.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + isFullyPopulatedDescriptor.name, + "isFullyPopulatedDescriptor", + ); + }); + }); +}); + +describe("isGenericDescriptor", () => { + it("[[Call]] returns true for a generic descriptor", () => { + assertStrictEquals(isGenericDescriptor({}), true); + }); + + it("[[Get]] returns false for a data descriptor", () => { + assertStrictEquals( + isGenericDescriptor({ value: undefined }), + false, + ); + assertStrictEquals(isGenericDescriptor({ writable: true }), false); + }); + + it("[[Get]] returns false for an accessor descriptor", () => { + assertStrictEquals(isGenericDescriptor({ get: undefined }), false); + assertStrictEquals(isGenericDescriptor({ set: undefined }), false); + }); + + it("[[Get]] returns false for undefined", () => { + assertStrictEquals(isGenericDescriptor(undefined), false); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new isGenericDescriptor({})); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(isGenericDescriptor.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + isGenericDescriptor.name, + "isGenericDescriptor", + ); + }); + }); +}); + describe("ordinaryToPrimitive", () => { it("[[Call]] prefers `valueOf` by default", () => { const obj = { @@ -202,83 +581,301 @@ describe("ordinaryToPrimitive", () => { }; assertThrows(() => ordinaryToPrimitive(obj)); }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new ordinaryToPrimitive("")); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(ordinaryToPrimitive.length, 2); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + ordinaryToPrimitive.name, + "ordinaryToPrimitive", + ); + }); + }); }); describe("sameValue", () => { it("[[Call]] returns false for null 🆚 undefined", () => { - assert(!sameValue(null, void {})); + assertStrictEquals(sameValue(null, undefined), false); }); it("[[Call]] returns false for null 🆚 an object", () => { - assert(!sameValue(null, {})); + assertStrictEquals(sameValue(null, {}), false); }); it("[[Call]] returns true for null 🆚 null", () => { - assert(sameValue(null, null)); + assertStrictEquals(sameValue(null, null), true); }); it("[[Call]] returns false for two different objects", () => { - assert(!sameValue({}, {})); + assertStrictEquals(sameValue({}, {}), false); }); it("[[Call]] returns true for the same object", () => { const obj = {}; - assert(sameValue(obj, obj)); + assertStrictEquals(sameValue(obj, obj), true); }); it("[[Call]] returns false for ±0", () => { - assert(!sameValue(0, -0)); + assertStrictEquals(sameValue(0, -0), false); }); it("[[Call]] returns true for -0", () => { - assert(sameValue(-0, -0)); + assertStrictEquals(sameValue(-0, -0), true); }); it("[[Call]] returns true for nan", () => { - assert(sameValue(0 / 0, 0 / 0)); + assertStrictEquals(sameValue(0 / 0, 0 / 0), true); }); it("[[Call]] returns false for a primitive and its wrapped object", () => { - assert(!sameValue(false, new Boolean(false))); + assertStrictEquals(sameValue(false, new Boolean(false)), false); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new sameValue(true, true)); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(sameValue.length, 2); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals(sameValue.name, "sameValue"); + }); }); }); describe("sameValueZero", () => { it("[[Call]] returns false for null 🆚 undefined", () => { - assert(!sameValueZero(null, void {})); + assertStrictEquals(sameValueZero(null, undefined), false); }); it("[[Call]] returns false for null 🆚 an object", () => { - assert(!sameValueZero(null, {})); + assertStrictEquals(sameValueZero(null, {}), false); }); it("[[Call]] returns true for null 🆚 null", () => { - assert(sameValueZero(null, null)); + assertStrictEquals(sameValueZero(null, null), true); }); it("[[Call]] returns false for two different objects", () => { - assert(!sameValueZero({}, {})); + assertStrictEquals(sameValueZero({}, {}), false); }); it("[[Call]] returns true for the same object", () => { const obj = {}; - assert(sameValueZero(obj, obj)); + assertStrictEquals(sameValueZero(obj, obj), true); }); it("[[Call]] returns true for ±0", () => { - assert(sameValueZero(0, -0)); + assertStrictEquals(sameValueZero(0, -0), true); }); it("[[Call]] returns true for -0", () => { - assert(sameValueZero(-0, -0)); + assertStrictEquals(sameValueZero(-0, -0), true); }); it("[[Call]] returns true for nan", () => { - assert(sameValueZero(0 / 0, 0 / 0)); + assertStrictEquals(sameValueZero(0 / 0, 0 / 0), true); }); it("[[Call]] returns false for a primitive and its wrapped object", () => { - assert(!sameValueZero(false, new Boolean(false))); + assertStrictEquals( + sameValueZero(false, new Boolean(false)), + false, + ); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new sameValueZero(true, true)); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(sameValueZero.length, 2); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals(sameValueZero.name, "sameValueZero"); + }); + }); +}); + +describe("toFunctionName", () => { + it("[[Call]] works with strings and no prefix", () => { + assertStrictEquals(toFunctionName("etaoin"), "etaoin"); + }); + + it("[[Call]] works with objects and no prefix", () => { + assertStrictEquals( + toFunctionName({ + toString() { + return "etaoin"; + }, + }), + "etaoin", + ); + }); + + it("[[Call]] works with descriptionless symbols and no prefix", () => { + assertStrictEquals(toFunctionName(Symbol()), ""); + }); + + it("[[Call]] works with empty description symbols and no prefix", () => { + assertStrictEquals(toFunctionName(Symbol("")), "[]"); + }); + + it("[[Call]] works with described symbols and no prefix", () => { + assertStrictEquals(toFunctionName(Symbol("etaoin")), "[etaoin]"); + }); + + it("[[Call]] works with strings and a prefix", () => { + assertStrictEquals(toFunctionName("etaoin", "foo"), "foo etaoin"); + }); + + it("[[Call]] works with objects and no prefix", () => { + assertStrictEquals( + toFunctionName({ + toString() { + return "etaoin"; + }, + }, "foo"), + "foo etaoin", + ); + }); + + it("[[Call]] works with descriptionless symbols and no prefix", () => { + assertStrictEquals(toFunctionName(Symbol(), "foo"), "foo "); + }); + + it("[[Call]] works with empty description symbols and no prefix", () => { + assertStrictEquals(toFunctionName(Symbol(""), "foo"), "foo []"); + }); + + it("[[Call]] works with described symbols and no prefix", () => { + assertStrictEquals( + toFunctionName(Symbol("etaoin"), "foo"), + "foo [etaoin]", + ); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new toFunctionName("")); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(toFunctionName.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + toFunctionName.name, + "toFunctionName", + ); + }); + }); +}); + +describe("toIndex", () => { + it("[[Call]] returns an index", () => { + assertStrictEquals(toIndex(9007199254740991), 9007199254740991); + }); + + it("[[Call]] returns zero for a zerolike argument", () => { + assertStrictEquals(toIndex(NaN), 0); + assertStrictEquals(toIndex("failure"), 0); + assertStrictEquals(toIndex(-0), 0); + }); + + it("[[Call]] rounds down to the nearest integer", () => { + assertStrictEquals(toIndex(0.25), 0); + assertStrictEquals(toIndex(1.1), 1); + }); + + it("[[Call]] throws when provided a negative number", () => { + assertThrows(() => toIndex(-1)); + assertThrows(() => toIndex(-Infinity)); + }); + + it("[[Call]] throws when provided a number greater than or equal to 2 ** 53", () => { + assertThrows(() => toIndex(9007199254740992)); + assertThrows(() => toIndex(Infinity)); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new toIndex(0)); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(toIndex.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals(toIndex.name, "toIndex"); + }); + }); +}); + +describe("toLength", () => { + it("[[Call]] returns a length", () => { + assertStrictEquals(toLength(9007199254740991), 9007199254740991); + }); + + it("[[Call]] returns zero for a nan argument", () => { + assertStrictEquals(toLength(NaN), 0); + assertStrictEquals(toLength("failure"), 0); + }); + + it("[[Call]] rounds down to the nearest integer", () => { + assertStrictEquals(toLength(0.25), 0); + assertStrictEquals(toLength(1.1), 1); + }); + + it("[[Call]] returns a result greater than or equal to zero", () => { + assertStrictEquals(toLength(-0), 0); + assertStrictEquals(toLength(-1), 0); + assertStrictEquals(toLength(-Infinity), 0); + }); + + it("[[Call]] returns a result less than 2 ** 53", () => { + assertStrictEquals(toLength(9007199254740992), 9007199254740991); + assertStrictEquals(toLength(Infinity), 9007199254740991); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new toLength(0)); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(toLength.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals(toLength.name, "toLength"); + }); }); }); @@ -353,7 +950,7 @@ describe("toPrimitive", () => { }, }, ); - assertStrictEquals(toPrimitive(value, "default"), "success"); + assertStrictEquals(toPrimitive(value), "success"); }); it("[[Call]] throws for an invalid hint", () => { @@ -377,6 +974,63 @@ describe("toPrimitive", () => { assertThrows(() => toPrimitive(value2, "badhint")); assertThrows(() => toPrimitive(true, "badhint")); }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new toPrimitive(true)); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(toPrimitive.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals(toPrimitive.name, "toPrimitive"); + }); + }); +}); + +describe("toPropertyKey", () => { + it("returns a string or symbol", () => { + const sym = Symbol(); + assertStrictEquals(toPropertyKey(sym), sym); + assertStrictEquals( + toPropertyKey(new String("success")), + "success", + ); + }); + + it("favours the `toString` representation", () => { + assertStrictEquals( + toPropertyKey({ + toString() { + return "success"; + }, + valueOf() { + return "failure"; + }, + }), + "success", + ); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new toPropertyKey("")); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(toPropertyKey.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals(toPropertyKey.name, "toPropertyKey"); + }); + }); }); describe("type", () => { @@ -399,4 +1053,38 @@ describe("type", () => { it('[[Call]] returns "object" for constructable objects', () => { assertStrictEquals(type(class {}), "object"); }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new type({})); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(type.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals(type.name, "type"); + }); + }); +}); + +describe("Ε", () => { + it("[[Get]] is ε", () => { + assertStrictEquals(Ε, Number.EPSILON); + }); +}); + +describe("Π", () => { + it("[[Get]] is π", () => { + assertStrictEquals(Π, Math.PI); + }); +}); + +describe("ℇ", () => { + it("[[Get]] is ℇ", () => { + assertStrictEquals(ℇ, Math.E); + }); });