X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/50ab30fc3a257e46da6b8bdc0dad054f729e16e1..07762ac4c632a6436d43d50d58c8d91760e81e44:/value.test.js?ds=sidebyside diff --git a/value.test.js b/value.test.js index 0f95f22..c55b591 100644 --- a/value.test.js +++ b/value.test.js @@ -1,16 +1,17 @@ -// β™“πŸŒŸ PiscΔ“s ∷ value.test.js -// ==================================================================== -// -// Copyright Β© 2022–2023 Lady [@ Lady’s Computer]. -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at . +// SPDX-FileCopyrightText: 2022, 2023, 2025 Lady +// SPDX-License-Identifier: MPL-2.0 +/** + * ⁌ β™“πŸŒŸ PiscΔ“s ∷ value.test.js + * + * Copyright Β© 2022–2023, 2025 Lady [@ Ladys Computer]. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at . + */ import { - assert, assertEquals, - assertNotStrictEquals, assertStrictEquals, assertThrows, describe, @@ -18,19 +19,21 @@ import { } from "./dev-deps.js"; import { ASYNC_ITERATOR, + canonicalNumericIndexSting, completePropertyDescriptor, HAS_INSTANCE, IS_CONCAT_SPREADABLE, isAccessorDescriptor, + isArrayIndexString, isDataDescriptor, isFullyPopulatedDescriptor, isGenericDescriptor, - isPropertyDescriptorRecord, + isIntegerIndexString, ITERATOR, - LN10, - LN2, - LOG10ℇ, - LOG2ℇ, + LN_10, + LN_2, + LOG10_𝑒, + LOG2_𝑒, MATCH, MATCH_ALL, MAXIMUM_NUMBER, @@ -44,26 +47,26 @@ import { ordinaryToPrimitive, POSITIVE_INFINITY, POSITIVE_ZERO, - RECIPROCAL_SQRT2, + RECIPROCAL_SQRT_2, REPLACE, sameValue, sameValueZero, SPECIES, SPLIT, - SQRT2, + SQRT_2, TO_PRIMITIVE, TO_STRING_TAG, toFunctionName, toIndex, toLength, toPrimitive, - toPropertyDescriptor, + toPropertyKey, type, UNDEFINED, UNSCOPABLES, - Ξ•, - Ξ , - ℇ, + 𝑒, + πœ€, + πœ‹, } from "./value.js"; describe("ASYNC_ITERATOR", () => { @@ -93,27 +96,27 @@ describe("ITERATOR", () => { }); }); -describe("LN10", () => { +describe("LN_10", () => { it("[[Get]] is ln(10)", () => { - assertStrictEquals(LN10, Math.LN10); + assertStrictEquals(LN_10, Math.LN10); }); }); -describe("LN2", () => { +describe("LN_2", () => { it("[[Get]] is ln(2)", () => { - assertStrictEquals(LN2, Math.LN2); + assertStrictEquals(LN_2, Math.LN2); }); }); -describe("LOG10ℇ", () => { - it("[[Get]] is log10(ℇ)", () => { - assertStrictEquals(LOG10ℇ, Math.LOG10E); +describe("LOG10_𝑒", () => { + it("[[Get]] is log10(𝑒)", () => { + assertStrictEquals(LOG10_𝑒, Math.LOG10E); }); }); -describe("LOG2ℇ", () => { +describe("LOG2_𝑒", () => { it("[[Get]] is log2(ℇ)", () => { - assertStrictEquals(LOG2ℇ, Math.LOG2E); + assertStrictEquals(LOG2_𝑒, Math.LOG2E); }); }); @@ -195,9 +198,9 @@ describe("POSITIVE_ZERO", () => { }); }); -describe("RECIPROCAL_SQRT2", () => { +describe("RECIPROCAL_SQRT_2", () => { it("[[Get]] is sqrt(Β½)", () => { - assertStrictEquals(RECIPROCAL_SQRT2, Math.SQRT1_2); + assertStrictEquals(RECIPROCAL_SQRT_2, Math.SQRT1_2); }); }); @@ -219,9 +222,9 @@ describe("SPLIT", () => { }); }); -describe("SQRT2", () => { +describe("SQRT_2", () => { it("[[Get]] is sqrt(2)", () => { - assertStrictEquals(SQRT2, Math.SQRT2); + assertStrictEquals(SQRT_2, Math.SQRT2); }); }); @@ -249,6 +252,59 @@ describe("UNSCOPABLES", () => { }); }); +describe("canonicalNumericIndexString", () => { + it("[[Call]] returns undefined for nonstrings", () => { + assertStrictEquals(canonicalNumericIndexString(1), void {}); + }); + + it("[[Call]] returns undefined for noncanonical strings", () => { + assertStrictEquals(canonicalNumericIndexString(""), void {}); + assertStrictEquals(canonicalNumericIndexString("01"), void {}); + assertStrictEquals( + canonicalNumericIndexString("9007199254740993"), + void {}, + ); + }); + + it('[[Call]] returns -0 for "-0"', () => { + assertStrictEquals(canonicalNumericIndexString("-0"), -0); + }); + + it("[[Call]] returns the corresponding number for canonical strings", () => { + assertStrictEquals(canonicalNumericIndexString("0"), 0); + assertStrictEquals(canonicalNumericIndexString("-0.25"), -0.25); + assertStrictEquals( + canonicalNumericIndexString("9007199254740992"), + 9007199254740992, + ); + assertStrictEquals(canonicalNumericIndexString("NaN"), 0 / 0); + assertStrictEquals(canonicalNumericIndexString("Infinity"), 1 / 0); + assertStrictEquals( + canonicalNumericIndexString("-Infinity"), + -1 / 0, + ); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new canonicalNumericIndexString("")); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(canonicalNumericIndexString.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + canonicalNumericIndexString.name, + "canonicalNumericIndexString", + ); + }); + }); +}); + describe("completePropertyDescriptor", () => { it("[[Call]] completes a generic descriptor", () => { const desc = {}; @@ -352,6 +408,69 @@ describe("isAccessorDescriptor", () => { }); }); +describe("isArrayIndexString", () => { + it("[[Call]] returns false for nonstrings", () => { + assertStrictEquals(isArrayIndexString(1), false); + }); + + it("[[Call]] returns false for noncanonical strings", () => { + assertStrictEquals(isArrayIndexString(""), false); + assertStrictEquals(isArrayIndexString("01"), false); + assertStrictEquals(isArrayIndexString("9007199254740993"), false); + }); + + it("[[Call]] returns false for nonfinite numbers", () => { + assertStrictEquals(isArrayIndexString("NaN"), false); + assertStrictEquals(isArrayIndexString("Infinity"), false); + assertStrictEquals(isArrayIndexString("-Infinity"), false); + }); + + it("[[Call]] returns false for negative numbers", () => { + assertStrictEquals(isArrayIndexString("-0"), false); + assertStrictEquals(isArrayIndexString("-1"), false); + }); + + it("[[Call]] returns false for nonintegers", () => { + assertStrictEquals(isArrayIndexString("0.25"), false); + assertStrictEquals(isArrayIndexString("1.1"), false); + }); + + it("[[Call]] returns false for numbers greater than or equal to -1 >>> 0", () => { + assertStrictEquals(isArrayIndexString(String(-1 >>> 0)), false); + assertStrictEquals( + isArrayIndexString(String((-1 >>> 0) + 1)), + false, + ); + }); + + it("[[Call]] returns true for array lengths less than -1 >>> 0", () => { + assertStrictEquals(isArrayIndexString("0"), true); + assertStrictEquals( + isArrayIndexString(String((-1 >>> 0) - 1)), + true, + ); + }); + + it("[[Construct]] throws an error", () => { + assertThrows(() => new isArrayIndexString("0")); + }); + + describe(".length", () => { + it("[[Get]] returns the correct length", () => { + assertStrictEquals(isArrayIndexString.length, 1); + }); + }); + + describe(".name", () => { + it("[[Get]] returns the correct name", () => { + assertStrictEquals( + isArrayIndexString.name, + "isArrayIndexString", + ); + }); + }); +}); + describe("isDataDescriptor", () => { it("[[Call]] returns false for a generic descriptor", () => { assertStrictEquals(isDataDescriptor({}), false); @@ -505,40 +624,63 @@ describe("isGenericDescriptor", () => { }); }); -describe("isPropertyDescriptorRecord", () => { - it("[[Call]] returns true for objects created by toPropertyDescriptor", () => { +describe("isIntegerIndexString", () => { + it("[[Call]] returns false for nonstrings", () => { + assertStrictEquals(isIntegerIndexString(1), false); + }); + + it("[[Call]] returns false for noncanonical strings", () => { + assertStrictEquals(isIntegerIndexString(""), false); + assertStrictEquals(isIntegerIndexString("01"), false); assertStrictEquals( - isPropertyDescriptorRecord(toPropertyDescriptor({})), - true, + isIntegerIndexString("9007199254740993"), + false, ); }); - it("[[Get]] returns false for other objects", () => { + it("[[Call]] returns false for nonfinite numbers", () => { + assertStrictEquals(isIntegerIndexString("NaN"), false); + assertStrictEquals(isIntegerIndexString("Infinity"), false); + assertStrictEquals(isIntegerIndexString("-Infinity"), false); + }); + + it("[[Call]] returns false for negative numbers", () => { + assertStrictEquals(isIntegerIndexString("-0"), false); + assertStrictEquals(isIntegerIndexString("-1"), false); + }); + + it("[[Call]] returns false for nonintegers", () => { + assertStrictEquals(isIntegerIndexString("0.25"), false); + assertStrictEquals(isIntegerIndexString("1.1"), false); + }); + + it("[[Call]] returns false for numbers greater than or equal to 2 ** 53", () => { assertStrictEquals( - isPropertyDescriptorRecord(Object.create(null)), + isIntegerIndexString("9007199254740992"), false, ); }); - it("[[Get]] returns false for undefined", () => { - assertStrictEquals(isPropertyDescriptorRecord(undefined), false); + it("[[Call]] returns true for safe canonical integer strings", () => { + assertStrictEquals(isIntegerIndexString("0"), true); + assertStrictEquals(isIntegerIndexString("9007199254740991"), true); }); it("[[Construct]] throws an error", () => { - assertThrows(() => new isPropertyDescriptorRecord({})); + assertThrows(() => new isIntegerIndexString("0")); }); describe(".length", () => { it("[[Get]] returns the correct length", () => { - assertStrictEquals(isPropertyDescriptorRecord.length, 1); + assertStrictEquals(isIntegerIndexString.length, 1); }); }); describe(".name", () => { it("[[Get]] returns the correct name", () => { assertStrictEquals( - isPropertyDescriptorRecord.name, - "isPropertyDescriptorRecord", + isIntegerIndexString.name, + "isIntegerIndexString", ); }); }); @@ -1034,274 +1176,43 @@ describe("toPrimitive", () => { }); }); -describe("toPropertyDescriptor", () => { - it("[[Call]] creates a new property descriptor record", () => { - const obj = {}; - const desc = toPropertyDescriptor(obj); - assertEquals(obj, desc); - assertNotStrictEquals(obj, desc); +describe("toPropertyKey", () => { + it("returns a string or symbol", () => { + const sym = Symbol(); + assertStrictEquals(toPropertyKey(sym), sym); + assertStrictEquals( + toPropertyKey(new String("success")), + "success", + ); }); - it("[[Call]] coerces the values", () => { - assertEquals( - toPropertyDescriptor({ - configurable: undefined, - enumerable: undefined, - writable: undefined, + it("favours the `toString` representation", () => { + assertStrictEquals( + toPropertyKey({ + toString() { + return "success"; + }, + valueOf() { + return "failure"; + }, }), - { configurable: false, enumerable: false, writable: false }, + "success", ); }); - it("[[Construct]] throws for primitives", () => { - assertThrows(() => toPropertyDescriptor(undefined)); - assertThrows(() => toPropertyDescriptor("failure")); - }); - it("[[Construct]] throws an error", () => { - assertThrows(() => new toPropertyDescriptor({})); + assertThrows(() => new toPropertyKey("")); }); describe(".length", () => { it("[[Get]] returns the correct length", () => { - assertStrictEquals(toPropertyDescriptor.length, 1); + assertStrictEquals(toPropertyKey.length, 1); }); }); describe(".name", () => { it("[[Get]] returns the correct name", () => { - assertStrictEquals( - toPropertyDescriptor.name, - "toPropertyDescriptor", - ); - }); - }); - - describe("~configurable", () => { - it("[[DefineOwnProperty]] coerces to a boolean", () => { - const desc = toPropertyDescriptor({}); - Object.defineProperty(desc, "configurable", {}); - assertStrictEquals(desc.configurable, false); - }); - - it("[[DefineOwnProperty]] throws for accessor properties", () => { - const desc = toPropertyDescriptor({}); - assertThrows(() => - Object.defineProperty(desc, "configurable", { get: undefined }) - ); - }); - - it("[[Set]] coerces to a boolean", () => { - const desc = toPropertyDescriptor({}); - desc.configurable = undefined; - assertStrictEquals(desc.configurable, false); - }); - - it("[[Delete]] works", () => { - const desc = toPropertyDescriptor({ configurable: false }); - delete desc.configurable; - assert(!("configurable" in desc)); - }); - }); - - describe("~enumerable", () => { - it("[[DefineOwnProperty]] coerces to a boolean", () => { - const desc = toPropertyDescriptor({}); - Object.defineProperty(desc, "enumerable", {}); - assertStrictEquals(desc.enumerable, false); - }); - - it("[[DefineOwnProperty]] throws for accessor properties", () => { - const desc = toPropertyDescriptor({}); - assertThrows(() => - Object.defineProperty(desc, "enumerable", { get: undefined }) - ); - }); - - it("[[Set]] coerces to a boolean", () => { - const desc = toPropertyDescriptor({}); - desc.enumerable = undefined; - assertStrictEquals(desc.enumerable, false); - }); - - it("[[Delete]] works", () => { - const desc = toPropertyDescriptor({ enumerable: false }); - delete desc.enumerable; - assert(!("enumerable" in desc)); - }); - }); - - describe("~get", () => { - it("[[DefineOwnProperty]] works", () => { - const desc = toPropertyDescriptor({}); - Object.defineProperty(desc, "get", {}); - assertStrictEquals(desc.get, undefined); - }); - - it("[[DefineOwnProperty]] throws for accessor properties", () => { - const desc = toPropertyDescriptor({}); - assertThrows(() => - Object.defineProperty(desc, "get", { get: undefined }) - ); - }); - - it("[[DefineOwnProperty]] throws if not callable or undefined", () => { - const desc = toPropertyDescriptor({}); - assertThrows( - () => Object.defineProperty(desc, "get", { value: null }), - ); - }); - - it("[[DefineOwnProperty]] throws if a data property is defined", () => { - const desc = toPropertyDescriptor({ value: undefined }); - assertThrows(() => Object.defineProperty(desc, "get", {})); - }); - - it("[[Set]] works", () => { - const desc = toPropertyDescriptor({}); - const fn = () => {}; - desc.get = fn; - assertStrictEquals(desc.get, fn); - }); - - it("[[Set]] throws if not callable or undefined", () => { - const desc = toPropertyDescriptor({}); - assertThrows(() => desc.get = null); - }); - - it("[[Set]] throws if a data property is defined", () => { - const desc = toPropertyDescriptor({ value: undefined }); - assertThrows(() => desc.get = undefined); - }); - - it("[[Delete]] works", () => { - const desc = toPropertyDescriptor({ get: undefined }); - delete desc.get; - assert(!("get" in desc)); - }); - }); - - describe("~set", () => { - it("[[DefineOwnProperty]] works", () => { - const desc = toPropertyDescriptor({}); - Object.defineProperty(desc, "set", {}); - assertStrictEquals(desc.set, undefined); - }); - - it("[[DefineOwnProperty]] throws for accessor properties", () => { - const desc = toPropertyDescriptor({}); - assertThrows(() => - Object.defineProperty(desc, "set", { get: undefined }) - ); - }); - - it("[[DefineOwnProperty]] throws if not callable or undefined", () => { - const desc = toPropertyDescriptor({}); - assertThrows( - () => Object.defineProperty(desc, "set", { value: null }), - ); - }); - - it("[[DefineOwnProperty]] throws if a data property is defined", () => { - const desc = toPropertyDescriptor({ value: undefined }); - assertThrows(() => Object.defineProperty(desc, "set", {})); - }); - - it("[[Set]] works", () => { - const desc = toPropertyDescriptor({}); - const fn = (_) => {}; - desc.set = fn; - assertStrictEquals(desc.set, fn); - }); - - it("[[Set]] throws if not callable or undefined", () => { - const desc = toPropertyDescriptor({}); - assertThrows(() => desc.set = null); - }); - - it("[[Set]] throws if a data property is defined", () => { - const desc = toPropertyDescriptor({ value: undefined }); - assertThrows(() => desc.set = undefined); - }); - - it("[[Delete]] works", () => { - const desc = toPropertyDescriptor({ set: undefined }); - delete desc.set; - assert(!("set" in desc)); - }); - }); - - describe("~value", () => { - it("[[DefineOwnProperty]] works", () => { - const desc = toPropertyDescriptor({}); - Object.defineProperty(desc, "value", {}); - assertStrictEquals(desc.value, undefined); - }); - - it("[[DefineOwnProperty]] throws for accessor properties", () => { - const desc = toPropertyDescriptor({}); - assertThrows(() => - Object.defineProperty(desc, "value", { get: undefined }) - ); - }); - - it("[[DefineOwnProperty]] throws if an accessor property is defined", () => { - const desc = toPropertyDescriptor({ get: undefined }); - assertThrows(() => Object.defineProperty(desc, "value", {})); - }); - - it("[[Set]] works", () => { - const desc = toPropertyDescriptor({}); - desc.value = "success"; - assertStrictEquals(desc.value, "success"); - }); - - it("[[Set]] throws if an accessor property is defined", () => { - const desc = toPropertyDescriptor({ get: undefined }); - assertThrows(() => desc.value = null); - }); - - it("[[Delete]] works", () => { - const desc = toPropertyDescriptor({ value: undefined }); - delete desc.value; - assert(!("value" in desc)); - }); - }); - - describe("~writable", () => { - it("[[DefineOwnProperty]] coerces to a boolean", () => { - const desc = toPropertyDescriptor({}); - Object.defineProperty(desc, "writable", {}); - assertStrictEquals(desc.writable, false); - }); - - it("[[DefineOwnProperty]] throws for accessor properties", () => { - const desc = toPropertyDescriptor({}); - assertThrows(() => - Object.defineProperty(desc, "writable", { get: undefined }) - ); - }); - - it("[[DefineOwnProperty]] throws if an accessor property is defined", () => { - const desc = toPropertyDescriptor({ get: undefined }); - assertThrows(() => Object.defineProperty(desc, "writable", {})); - }); - - it("[[Set]] coerces to a boolean", () => { - const desc = toPropertyDescriptor({}); - desc.writable = undefined; - assertStrictEquals(desc.writable, false); - }); - - it("[[Set]] throws if an accessor property is defined", () => { - const desc = toPropertyDescriptor({ get: undefined }); - assertThrows(() => desc.writable = false); - }); - - it("[[Delete]] works", () => { - const desc = toPropertyDescriptor({ writable: false }); - delete desc.writable; - assert(!("writable" in desc)); + assertStrictEquals(toPropertyKey.name, "toPropertyKey"); }); }); }); @@ -1344,20 +1255,20 @@ describe("type", () => { }); }); -describe("Ξ•", () => { - it("[[Get]] is Ξ΅", () => { - assertStrictEquals(Ξ•, Number.EPSILON); +describe("𝑒", () => { + it("[[Get]] is 𝑒", () => { + assertStrictEquals(𝑒, Math.E); }); }); -describe("Ξ ", () => { - it("[[Get]] is Ο€", () => { - assertStrictEquals(Ξ , Math.PI); +describe("πœ€", () => { + it("[[Get]] is πœ€", () => { + assertStrictEquals(πœ€, Number.EPSILON); }); }); -describe("ℇ", () => { - it("[[Get]] is ℇ", () => { - assertStrictEquals(ℇ, Math.E); +describe("πœ‹", () => { + it("[[Get]] is πœ‹", () => { + assertStrictEquals(πœ‹, Math.PI); }); });