-// ♓🌟 Piscēs ∷ collection.test.js
-// ====================================================================
-//
-// Copyright © 2022 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 <https://mozilla.org/MPL/2.0/>.
+// SPDX-FileCopyrightText: 2022, 2023, 2025 Lady <https://www.ladys.computer/about/#lady>
+// SPDX-License-Identifier: MPL-2.0
+/**
+ * ⁌ ♓🧩 Piscēs ∷ collection.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 <https://mozilla.org/MPL/2.0/>.
+ */
import {
assertEquals,
spy,
} from "./dev-deps.js";
import {
- canonicalNumericIndexString,
- findIndexedEntry,
- isArrayIndexString,
+ array,
+ concatSpreadableCatenate,
+ copyWithin,
+ denseProxy,
+ fill,
+ filter,
+ findFirstIndex,
+ findFirstIndexedEntry,
+ findFirstItem,
+ findLastIndex,
+ findLastIndexedEntry,
+ findLastItem,
+ flatmap,
+ flatten as _flatten /* TK */,
+ getFirstIndex as _getFirstIndex /* TK */,
+ getItem as _getItem /* TK */,
+ getLastIndex as _getLastIndex /* TK */,
+ hasEvery as _hasEvery /* TK */,
+ hasSome as _hasSome /* TK */,
+ includes as _includes /* TK */,
+ indexedEntries as _indexedEntries /* TK */,
+ indices as _indices /* TK */,
+ isArray as _isArray /* TK */,
isCollection,
- isConcatSpreadable,
- isIntegerIndexString,
- lengthOfArrayLike,
- toIndex,
- toLength,
+ isDenseProxy,
+ items as _items /* TK */,
+ map as _map /* TK */,
+ pop as _pop /* TK */,
+ push as _push /* TK */,
+ reduce as _reduce /* TK */,
+ reverse as _reverse /* TK */,
+ shift as _shift /* TK */,
+ slice as _slice /* TK */,
+ sort as _sort /* TK */,
+ splice as _splice /* TK */,
+ toArray,
+ toDenseArray,
+ unshift as _unshift /* TK */,
} from "./collection.js";
-describe("canonicalNumericIndexString", () => {
- it("[[Call]] returns undefined for nonstrings", () => {
- assertStrictEquals(canonicalNumericIndexString(1), void {});
+describe("array", () => {
+ it("[[Call]] returns an array of the provided values", () => {
+ assertEquals(array("etaoin", [], true), ["etaoin", [], true]);
});
- it("[[Call]] returns undefined for noncanonical strings", () => {
- assertStrictEquals(canonicalNumericIndexString(""), void {});
- assertStrictEquals(canonicalNumericIndexString("01"), void {});
+ it("[[Call]] returns an empty array with no arguments", () => {
+ assertEquals(array(), []);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new array());
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(array.length, 0);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(array.name, "array");
+ });
+ });
+});
+
+describe("concatSpreadableCatenate", () => {
+ it("[[Call]] catenates concat spreadable values", () => {
+ assertEquals(
+ concatSpreadableCatenate([1, 2], [2, [3]], {
+ length: 1,
+ [Symbol.isConcatSpreadable]: true,
+ }),
+ [1, 2, 2, [3], ,],
+ );
+ });
+
+ it("[[Call]] does not catenate other values", () => {
+ assertEquals(concatSpreadableCatenate({}, "etaoin"), [
+ {},
+ "etaoin",
+ ]);
+ });
+
+ it("[[Call]] allows a nullish first argument", () => {
+ assertEquals(concatSpreadableCatenate(null), [null]);
+ assertEquals(concatSpreadableCatenate(undefined), [undefined]);
+ });
+
+ it("[[Call]] returns an empty array with no arguments", () => {
+ assertEquals(concatSpreadableCatenate(), []);
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new concatSpreadableCatenate());
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(concatSpreadableCatenate.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ concatSpreadableCatenate.name,
+ "concatSpreadableCatenate",
+ );
+ });
+ });
+});
+
+describe("copyWithin", () => {
+ it("[[Call]] copies within", () => {
+ assertEquals(
+ copyWithin(["a", "b", "c", , "e"], 0, 3, 4),
+ [, "b", "c", , "e"],
+ );
+ assertEquals(
+ copyWithin(["a", "b", "c", , "e"], 1, 3),
+ ["a", , "e", , "e"],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new copyWithin([], 0, 0));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(copyWithin.length, 3);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(copyWithin.name, "copyWithin");
+ });
+ });
+});
+
+describe("denseProxy", () => {
+ const makeUnderlying = () =>
+ Object.create({ 2: "inherited" }, {
+ // 0 is not present
+ 1: { value: "static", configurable: true, writable: true },
+ // 2 is not an own property, but is present on the prototype
+ 3: { configurable: true, get: () => "dynamic" },
+ length: { value: "4", configurable: true, writable: true },
+ });
+
+ it("[[Call]] returns an object which inherits from the provided object", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Object.getPrototypeOf(proxy),
+ underlying,
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new denseProxy([]));
+ });
+
+ it("[[OwnPropertyKeys]] lists integer indices, then the length, then other keys", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ const sym = Symbol();
+ proxy[sym] = "shrdlu";
+ proxy["1.2.3"] = "etaion";
+ assertEquals(
+ Reflect.ownKeys(proxy),
+ ["0", "1", "2", "3", "length", "1.2.3", sym],
+ );
+ });
+
+ it("[[PreventExtensions]] fails if the underlying object is extensible", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.preventExtensions(proxy),
+ false,
+ );
+ });
+
+ it("[[PreventExtensions]] fails if the underlying object has a nonconstant length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.defineProperty(underlying, "length", { get: () => 4 });
+ Object.freeze(underlying);
assertStrictEquals(
- canonicalNumericIndexString("9007199254740993"),
- void {},
+ Reflect.preventExtensions(proxy),
+ false,
+ );
+ });
+
+ it("[[PreventExtensions]] succeeds if the underlying object is non·extensible and has a constant length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.defineProperty(underlying, "length", {
+ configurable: false,
+ writable: false,
+ });
+ Object.preventExtensions(underlying);
+ assertStrictEquals(
+ Reflect.preventExtensions(proxy),
+ true,
+ );
+ });
+
+ it("[[SetPrototypeOf]] fails to change the prototype", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.setPrototypeOf(proxy, {}),
+ false,
+ );
+ });
+
+ it("[[SetPrototypeOf]] succeeds keeping the prototype the same", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.setPrototypeOf(proxy, underlying),
+ true,
+ );
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(denseProxy.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(denseProxy.name, "denseProxy");
+ });
+ });
+
+ describe("~[]", () => {
+ it("[[DefineProperty]] allows changes when the property is not an index property or length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ const newValue = Symbol();
+ proxy.etaoin = newValue;
+ assertStrictEquals(
+ proxy.etaoin,
+ newValue,
+ );
+ });
+
+ it("[[DefineProperty]] allows changing nothing when the property is not an own property", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "0",
+ {
+ configurable: true,
+ enumerable: true,
+ writable: false,
+ value: undefined,
+ },
+ ),
+ true,
+ );
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "2",
+ {
+ configurable: true,
+ enumerable: true,
+ writable: false,
+ value: undefined,
+ },
+ ),
+ true,
+ );
+ /* test nonconfigurable versions too */
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "0", { configurable: false });
+ Object.defineProperty(proxy, "2", { configurable: false });
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "0",
+ Object.getOwnPropertyDescriptor(proxy, "0"),
+ ),
+ true,
+ );
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "2",
+ Object.getOwnPropertyDescriptor(proxy, "2"),
+ ),
+ true,
+ );
+ });
+
+ it("[[DefineProperty]] allows changing nothing when the property is a data index property", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "1",
+ {
+ configurable: true,
+ enumerable: true,
+ writable: false,
+ value: underlying[1],
+ },
+ ),
+ true,
+ );
+ /* test nonconfigurable versions too */
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "1", { configurable: false });
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "1",
+ Object.getOwnPropertyDescriptor(proxy, "1"),
+ ),
+ true,
+ );
+ });
+
+ it("[[DefineProperty]] allows changing nothing when the property is an accessor index property", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "3",
+ {
+ configurable: true,
+ enumerable: true,
+ writable: false,
+ value: underlying[3],
+ },
+ ),
+ true,
+ );
+ /* test nonconfigurable versions too */
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "1", { configurable: false });
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "1",
+ Object.getOwnPropertyDescriptor(proxy, "1"),
+ ),
+ true,
+ );
+ });
+
+ it("[[DefineProperty]] does not allow a change in enumerablility on index properties", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, i, { enumerable: false }),
+ false,
+ );
+ }
+ });
+
+ it("[[DefineProperty]] does not allow a change in value on index properties", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, i, { value: "new value" })
+ && (() => {
+ throw i;
+ })(),
+ false,
+ );
+ }
+ });
+
+ it("[[DefineProperty]] does not allow a change in getter on index properties", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, i, {
+ get: () => underlying[i],
+ }) && (() => {
+ throw i;
+ })(),
+ false,
+ );
+ }
+ });
+
+ it("[[DefineProperty]] does not allow a change in setter on index properties", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, i, { set: () => undefined }),
+ false,
+ );
+ }
+ });
+
+ it("[[DefineProperty]] does not allow a change in configurability on index properties if the property in the underlying object may change", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.defineProperty(underlying, "length", {
+ configurable: false,
+ writable: false,
+ });
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, i, { configurable: false }),
+ false,
+ );
+ }
+ });
+
+ it("[[DefineProperty]] does not allow a change in configurability on index properties if the length of the underlying object may change", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.seal(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, i, { configurable: false }),
+ false,
+ );
+ }
+ });
+
+ it("[[DefineProperty]] allows a change in configurability on index properties when it is safe to do so", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.defineProperty(underlying, "length", {
+ configurable: false,
+ writable: false,
+ });
+ Object.defineProperty(underlying, "1", {
+ configurable: false,
+ writable: false,
+ });
+ Object.defineProperty(underlying, "3", { configurable: false });
+ Object.preventExtensions(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, i, { configurable: false }),
+ true,
+ );
+ }
+ });
+
+ it("[[Delete]] is allowed when the property is not an index property or length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ proxy.a = "etaoin";
+ assertStrictEquals(
+ Reflect.deleteProperty(proxy, "a"),
+ true,
+ );
+ assertStrictEquals(
+ Reflect.has(proxy, "a"),
+ false,
+ );
+ });
+
+ it("[[Delete]] is forbidden for index properties less than the length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.deleteProperty(proxy, i),
+ false,
+ );
+ }
+ });
+
+ it("[[Delete]] is allowed for index properties greater than or equal to the length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.deleteProperty(proxy, "4"),
+ true,
+ );
+ assertStrictEquals(
+ Reflect.deleteProperty(proxy, "5"),
+ true,
+ );
+ });
+
+ it("[[GetOwnProperty]] gives the value of an index property as a data property by default", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxy, 1),
+ {
+ configurable: true,
+ enumerable: true,
+ value: underlying[1],
+ writable: false,
+ },
+ );
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxy, 3),
+ {
+ configurable: true,
+ enumerable: true,
+ value: underlying[3],
+ writable: false,
+ },
+ );
+ /* test nonconfigurable data properties too */
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "1", { configurable: false });
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxy, 1),
+ {
+ configurable: false,
+ enumerable: true,
+ value: underlying[1],
+ writable: false,
+ },
+ );
+ });
+
+ it("[[GetOwnProperty]] gives a value of undefined if the underlying object does not have an index property as an own property", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxy, 0),
+ {
+ configurable: true,
+ enumerable: true,
+ value: undefined,
+ writable: false,
+ },
+ );
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxy, 2),
+ {
+ configurable: true,
+ enumerable: true,
+ value: undefined,
+ writable: false,
+ },
+ );
+ });
+
+ it("[[GetOwnProperty]] gives a value of undefined for index properties less than the length", () => {
+ const underlying = makeUnderlying();
+ underlying.length = 0;
+ const proxy = denseProxy(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(proxy, i),
+ undefined,
+ );
+ }
+ });
+
+ it("[[GetOwnProperty]] gives a getter when the underlying object has a getter and an index property is not configurable", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "3", { configurable: false });
+ const descriptor = Object.getOwnPropertyDescriptor(proxy, 3);
+ assertEquals(
+ descriptor,
+ {
+ configurable: false,
+ enumerable: true,
+ get: descriptor.get,
+ set: undefined,
+ },
+ );
+ });
+
+ describe("[[GetOwnProperty]].get.length", () => {
+ it("[[Get]] returns the correct length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "3", { configurable: false });
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ proxy,
+ "3",
+ ).get.length,
+ 0,
+ );
+ });
+ });
+
+ describe("[[GetOwnProperty]].get.name", () => {
+ it("[[Get]] returns the correct name", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "3", { configurable: false });
+ assertStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ proxy,
+ "3",
+ ).get.name,
+ "get 3",
+ );
+ });
+ });
+
+ it("[[HasProperty]] works when the property is not an index property or length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ proxy.a = "etaoin";
+ Object.getPrototypeOf(underlying).b = "shrdlu";
+ assertStrictEquals(
+ Reflect.has(proxy, "a"),
+ true,
+ );
+ assertStrictEquals(
+ Reflect.has(proxy, "b"),
+ true,
+ );
+ assertStrictEquals(
+ Reflect.has(proxy, "z"),
+ false,
+ );
+ });
+
+ it("[[HasProperty]] works for index properties less than the length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.has(proxy, i),
+ true,
+ );
+ }
+ delete underlying.length;
+ for (let i = 0; i < 4; ++i) {
+ assertStrictEquals(
+ Reflect.has(proxy, i),
+ Reflect.has(underlying, i),
+ );
+ }
+ });
+
+ it("[[HasProperty]] works for index properties greater than or equal to the length", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.has(proxy, "4"),
+ false,
+ );
+ assertStrictEquals(
+ Reflect.has(proxy, "5"),
+ false,
+ );
+ underlying[4] = "inherited now";
+ assertStrictEquals(
+ Reflect.has(proxy, "4"),
+ true,
+ );
+ });
+ });
+
+ describe("~length", () => {
+ it("[[DefineProperty]] allows changing nothing", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "length",
+ {
+ configurable: true,
+ enumerable: false,
+ writable: false,
+ value: underlying.length >>> 0,
+ },
+ ),
+ true,
+ );
+ /* test nonconfigurable versions too */
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "length", { configurable: false });
+ assertStrictEquals(
+ Reflect.defineProperty(
+ proxy,
+ "length",
+ Object.getOwnPropertyDescriptor(proxy, "length"),
+ ),
+ true,
+ );
+ });
+
+ it("[[DefineProperty]] does not allow a change in enumerablility", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, "length", { enumerable: true }),
+ false,
+ );
+ });
+
+ it("[[DefineProperty]] does not allow a change in value", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, "length", { value: 0 }),
+ false,
+ );
+ });
+
+ it("[[DefineProperty]] does not allow a change in getter", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, "length", {
+ get: () => underlying.length >>> 0,
+ }),
+ false,
+ );
+ });
+
+ it("[[DefineProperty]] does not allow a change in setter", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, "length", { set: () => {} }),
+ false,
+ );
+ });
+
+ it("[[DefineProperty]] does not allow a change in configurability if the length of the underlying object may change", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, "length", {
+ configurable: false,
+ }),
+ false,
+ );
+ Object.defineProperty(underlying, "length", {
+ configurable: false,
+ get: () => 0,
+ });
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, "length", {
+ configurable: false,
+ }),
+ false,
+ );
+ });
+
+ it("[[DefineProperty]] allows a change in configurability when it is safe to do so", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ Object.defineProperty(underlying, "length", {
+ configurable: false,
+ writable: false,
+ });
+ assertStrictEquals(
+ Reflect.defineProperty(proxy, "length", {
+ configurable: false,
+ }),
+ true,
+ );
+ });
+
+ it("[[Delete]] is forbidden", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.deleteProperty(
+ proxy,
+ "length",
+ ),
+ false,
+ );
+ });
+
+ it("[[GetOwnProperty]] gives the value as a data property", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxy, "length"),
+ {
+ configurable: true,
+ enumerable: false,
+ value: underlying.length >>> 0,
+ writable: false,
+ },
+ );
+ /* test nonconfigurable data properties too */
+ Object.freeze(underlying);
+ Object.defineProperty(proxy, "length", { configurable: false });
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxy, "length"),
+ {
+ configurable: false,
+ enumerable: false,
+ value: underlying.length >>> 0,
+ writable: false,
+ },
+ );
+ });
+
+ it("[[GetOwnProperty]] gives 0 if the underlying object does not have the property as an own property", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ delete underlying.length;
+ Object.getPrototypeOf(underlying).length = 3;
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxy, "length"),
+ {
+ configurable: true,
+ enumerable: false,
+ value: 0,
+ writable: false,
+ },
+ );
+ });
+
+ it("[[HasProperty]] is always true", () => {
+ const underlying = makeUnderlying();
+ const proxy = denseProxy(underlying);
+ assertStrictEquals(
+ Reflect.has(proxy, "length"),
+ true,
+ );
+ delete underlying.length;
+ assertStrictEquals(
+ Reflect.has(proxy, "length"),
+ true,
+ );
+ });
+ });
+});
+
+describe("fill", () => {
+ it("[[Call]] fills", () => {
+ assertEquals(
+ fill({ 1: "failure", length: 3 }, "success"),
+ { 0: "success", 1: "success", 2: "success", length: 3 },
+ );
+ });
+
+ it("[[Call]] can fill a range", () => {
+ assertEquals(
+ fill({ 1: "failure", length: 4 }, "success", 1, 3),
+ { 1: "success", 2: "success", length: 4 },
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new fill([], null));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(fill.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(fill.name, "fill");
+ });
+ });
+});
+
+describe("filter", () => {
+ it("[[Call]] filters", () => {
+ assertEquals(
+ filter(["failure", "success", ,], function ($) {
+ return !$ || $ == this;
+ }, "success"),
+ ["success"],
);
});
- it('[[Call]] returns -0 for "-0"', () => {
- assertStrictEquals(canonicalNumericIndexString("-0"), -0);
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new filter([], () => {}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(filter.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(filter.name, "filter");
+ });
+ });
+});
+
+describe("findFirstIndex", () => {
+ it("[[Call]] returns undefined if no matching entry exists", () => {
+ assertStrictEquals(findFirstIndex([], () => true), undefined);
+ assertStrictEquals(findFirstIndex([1], () => false), undefined);
+ });
+
+ it("[[Call]] returns an index for the first match", () => {
+ assertStrictEquals(
+ findFirstIndex([, true, false], ($) => $ ?? true),
+ 1,
+ );
+ assertStrictEquals(
+ findFirstIndex(
+ ["failure", "success", "success"],
+ ($) => $ == "success",
+ ),
+ 1,
+ );
});
- it("[[Call]] returns the corresponding number for canonical strings", () => {
- assertStrictEquals(canonicalNumericIndexString("0"), 0);
- assertStrictEquals(canonicalNumericIndexString("-0.25"), -0.25);
+ it("[[Call]] works on arraylike objects", () => {
assertStrictEquals(
- canonicalNumericIndexString("9007199254740992"),
- 9007199254740992,
+ findFirstIndex({ 1: "success", length: 2 }, ($) => $),
+ 1,
);
- assertStrictEquals(canonicalNumericIndexString("NaN"), 0 / 0);
- assertStrictEquals(canonicalNumericIndexString("Infinity"), 1 / 0);
assertStrictEquals(
- canonicalNumericIndexString("-Infinity"),
- -1 / 0,
+ findFirstIndex({ 1: "failure", length: 1 }, ($) => $),
+ undefined,
);
});
+
+ it("[[Call]] only gets the value once", () => {
+ const get1 = spy(() => true);
+ findFirstIndex({
+ get 1() {
+ return get1();
+ },
+ length: 2,
+ }, ($) => $);
+ assertSpyCalls(get1, 1);
+ });
+
+ it("[[Call]] passes the value, index, and this value to the callback", () => {
+ const arr = [, "failure", "success", "success"];
+ const callback = spy(($) => $ === "success");
+ const thisArg = {};
+ findFirstIndex(arr, callback, thisArg);
+ assertSpyCalls(callback, 2);
+ assertSpyCall(callback, 0, {
+ args: ["failure", 1, arr],
+ self: thisArg,
+ });
+ assertSpyCall(callback, 1, {
+ args: ["success", 2, arr],
+ self: thisArg,
+ });
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new findFirstIndex([], () => {}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(findFirstIndex.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(findFirstIndex.name, "findFirstIndex");
+ });
+ });
});
-describe("findIndexedEntry", () => {
+describe("findFirstIndexedEntry", () => {
it("[[Call]] returns undefined if no matching entry exists", () => {
- assertStrictEquals(findIndexedEntry([], () => true), void {});
- assertStrictEquals(findIndexedEntry([1], () => false), void {});
+ assertStrictEquals(
+ findFirstIndexedEntry([], () => true),
+ undefined,
+ );
+ assertStrictEquals(
+ findFirstIndexedEntry([1], () => false),
+ undefined,
+ );
});
it("[[Call]] returns an entry for the first match", () => {
assertEquals(
- findIndexedEntry([, true, false], ($) => $ ?? true),
- [0, void {}],
+ findFirstIndexedEntry([, true, false], ($) => $ ?? true),
+ [1, true],
);
assertEquals(
- findIndexedEntry(["failure", "success"], ($) => $ == "success"),
+ findFirstIndexedEntry(
+ ["failure", "success", "success"],
+ ($) => $ == "success",
+ ),
[1, "success"],
);
});
it("[[Call]] works on arraylike objects", () => {
assertEquals(
- findIndexedEntry({ 1: "success", length: 2 }, ($) => $),
+ findFirstIndexedEntry({ 1: "success", length: 2 }, ($) => $),
[1, "success"],
);
assertEquals(
- findIndexedEntry({ 1: "failure", length: 1 }, ($) => $),
- void {},
+ findFirstIndexedEntry({ 1: "failure", length: 1 }, ($) => $),
+ undefined,
);
});
it("[[Call]] only gets the value once", () => {
const get1 = spy(() => true);
- findIndexedEntry({
+ findFirstIndexedEntry({
get 1() {
return get1();
},
});
it("[[Call]] passes the value, index, and this value to the callback", () => {
- const arr = ["failure", "success", "success"];
+ const arr = [, "failure", "success", "success"];
const callback = spy(($) => $ === "success");
const thisArg = {};
- findIndexedEntry(arr, callback, thisArg);
+ findFirstIndexedEntry(arr, callback, thisArg);
assertSpyCalls(callback, 2);
assertSpyCall(callback, 0, {
- args: ["failure", 0, arr],
+ args: ["failure", 1, arr],
self: thisArg,
});
assertSpyCall(callback, 1, {
- args: ["success", 1, arr],
+ args: ["success", 2, arr],
+ self: thisArg,
+ });
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new findFirstIndexedEntry([], () => {}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(findFirstIndexedEntry.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ findFirstIndexedEntry.name,
+ "findFirstIndexedEntry",
+ );
+ });
+ });
+});
+
+describe("findFirstItem", () => {
+ it("[[Call]] returns undefined if no matching item exists", () => {
+ assertStrictEquals(findFirstItem([], () => true), undefined);
+ assertStrictEquals(findFirstItem([1], () => false), undefined);
+ });
+
+ it("[[Call]] returns the first match", () => {
+ assertStrictEquals(
+ findFirstItem([, true, false], ($) => $ ?? true),
+ true,
+ );
+ assertStrictEquals(
+ findFirstItem(
+ ["failure", "success", "success"],
+ ($) => $ == "success",
+ ),
+ "success",
+ );
+ });
+
+ it("[[Call]] works on arraylike objects", () => {
+ assertStrictEquals(
+ findFirstItem({ 1: "success", length: 2 }, ($) => $),
+ "success",
+ );
+ assertStrictEquals(
+ findFirstItem({ 1: "failure", length: 1 }, ($) => $),
+ undefined,
+ );
+ });
+
+ it("[[Call]] only gets the value once", () => {
+ const get1 = spy(() => true);
+ findFirstItem({
+ get 1() {
+ return get1();
+ },
+ length: 2,
+ }, ($) => $);
+ assertSpyCalls(get1, 1);
+ });
+
+ it("[[Call]] passes the value, index, and this value to the callback", () => {
+ const arr = [, "failure", "success", "success"];
+ const callback = spy(($) => $ === "success");
+ const thisArg = {};
+ findFirstItem(arr, callback, thisArg);
+ assertSpyCalls(callback, 2);
+ assertSpyCall(callback, 0, {
+ args: ["failure", 1, arr],
+ self: thisArg,
+ });
+ assertSpyCall(callback, 1, {
+ args: ["success", 2, arr],
self: thisArg,
});
});
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new findFirstItem([], () => {}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(findFirstItem.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(findFirstItem.name, "findFirstItem");
+ });
+ });
});
-describe("isArrayIndexString", () => {
- it("[[Call]] returns false for nonstrings", () => {
- assertStrictEquals(isArrayIndexString(1), false);
+describe("findLastIndex", () => {
+ it("[[Call]] returns undefined if no matching entry exists", () => {
+ assertStrictEquals(findLastIndex([], () => true), undefined);
+ assertStrictEquals(findLastIndex([1], () => false), undefined);
+ });
+
+ it("[[Call]] returns an index for the first match", () => {
+ assertStrictEquals(
+ findLastIndex([true, false, ,], ($) => $ ?? true),
+ 0,
+ );
+ assertStrictEquals(
+ findLastIndex(
+ ["success", "success", "failure"],
+ ($) => $ == "success",
+ ),
+ 1,
+ );
+ });
+
+ it("[[Call]] works on arraylike objects", () => {
+ assertStrictEquals(
+ findLastIndex({ 1: "success", length: 2 }, ($) => $),
+ 1,
+ );
+ assertStrictEquals(
+ findLastIndex({ 1: "failure", length: 1 }, ($) => $),
+ undefined,
+ );
+ });
+
+ it("[[Call]] only gets the value once", () => {
+ const get1 = spy(() => true);
+ findLastIndex({
+ get 1() {
+ return get1();
+ },
+ length: 2,
+ }, ($) => $);
+ assertSpyCalls(get1, 1);
});
- it("[[Call]] returns false for noncanonical strings", () => {
- assertStrictEquals(isArrayIndexString(""), false);
- assertStrictEquals(isArrayIndexString("01"), false);
- assertStrictEquals(isArrayIndexString("9007199254740993"), false);
+ it("[[Call]] passes the value, index, and this value to the callback", () => {
+ const arr = ["success", "success", "failure", ,];
+ const callback = spy(($) => $ === "success");
+ const thisArg = {};
+ findLastIndex(arr, callback, thisArg);
+ assertSpyCalls(callback, 2);
+ assertSpyCall(callback, 0, {
+ args: ["failure", 2, arr],
+ self: thisArg,
+ });
+ assertSpyCall(callback, 1, {
+ args: ["success", 1, arr],
+ self: thisArg,
+ });
});
- it("[[Call]] returns false for nonfinite numbers", () => {
- assertStrictEquals(isArrayIndexString("NaN"), false);
- assertStrictEquals(isArrayIndexString("Infinity"), false);
- assertStrictEquals(isArrayIndexString("-Infinity"), false);
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new findLastIndex([], () => {}));
});
- it("[[Call]] returns false for negative numbers", () => {
- assertStrictEquals(isArrayIndexString("-0"), false);
- assertStrictEquals(isArrayIndexString("-1"), false);
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(findLastIndex.length, 2);
+ });
});
- it("[[Call]] returns false for nonintegers", () => {
- assertStrictEquals(isArrayIndexString("0.25"), false);
- assertStrictEquals(isArrayIndexString("1.1"), false);
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(findLastIndex.name, "findLastIndex");
+ });
});
+});
- it("[[Call]] returns false for numbers greater than or equal to -1 >>> 0", () => {
- assertStrictEquals(isArrayIndexString(String(-1 >>> 0)), false);
+describe("findLastIndexedEntry", () => {
+ it("[[Call]] returns undefined if no matching entry exists", () => {
assertStrictEquals(
- isArrayIndexString(String((-1 >>> 0) + 1)),
- false,
+ findLastIndexedEntry([], () => true),
+ undefined,
+ );
+ assertStrictEquals(
+ findLastIndexedEntry([1], () => false),
+ undefined,
+ );
+ });
+
+ it("[[Call]] returns an index for the first match", () => {
+ assertEquals(
+ findLastIndexedEntry([true, false, ,], ($) => $ ?? true),
+ [0, true],
+ );
+ assertEquals(
+ findLastIndexedEntry(
+ ["success", "success", "failure"],
+ ($) => $ == "success",
+ ),
+ [1, "success"],
+ );
+ });
+
+ it("[[Call]] works on arraylike objects", () => {
+ assertEquals(
+ findLastIndexedEntry({ 1: "success", length: 2 }, ($) => $),
+ [1, "success"],
+ );
+ assertEquals(
+ findLastIndexedEntry({ 1: "failure", length: 1 }, ($) => $),
+ undefined,
);
});
- it("[[Call]] returns true for array lengths less than -1 >>> 0", () => {
- assertStrictEquals(isArrayIndexString("0"), true);
+ it("[[Call]] only gets the value once", () => {
+ const get1 = spy(() => true);
+ findLastIndexedEntry({
+ get 1() {
+ return get1();
+ },
+ length: 2,
+ }, ($) => $);
+ assertSpyCalls(get1, 1);
+ });
+
+ it("[[Call]] passes the value, index, and this value to the callback", () => {
+ const arr = ["success", "success", "failure", ,];
+ const callback = spy(($) => $ === "success");
+ const thisArg = {};
+ findLastIndexedEntry(arr, callback, thisArg);
+ assertSpyCalls(callback, 2);
+ assertSpyCall(callback, 0, {
+ args: ["failure", 2, arr],
+ self: thisArg,
+ });
+ assertSpyCall(callback, 1, {
+ args: ["success", 1, arr],
+ self: thisArg,
+ });
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new findLastIndexedEntry([], () => {}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(findLastIndexedEntry.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(
+ findLastIndexedEntry.name,
+ "findLastIndexedEntry",
+ );
+ });
+ });
+});
+
+describe("findLastItem", () => {
+ it("[[Call]] returns undefined if no matching entry exists", () => {
+ assertStrictEquals(findLastItem([], () => true), undefined);
+ assertStrictEquals(findLastItem([1], () => false), undefined);
+ });
+
+ it("[[Call]] returns an index for the first match", () => {
assertStrictEquals(
- isArrayIndexString(String((-1 >>> 0) - 1)),
+ findLastItem([true, false, ,], ($) => $ ?? true),
true,
);
+ assertStrictEquals(
+ findLastItem(
+ ["success", "success", "failure"],
+ ($) => $ == "success",
+ ),
+ "success",
+ );
+ });
+
+ it("[[Call]] works on arraylike objects", () => {
+ assertStrictEquals(
+ findLastItem({ 1: "success", length: 2 }, ($) => $),
+ "success",
+ );
+ assertStrictEquals(
+ findLastItem({ 1: "failure", length: 1 }, ($) => $),
+ undefined,
+ );
+ });
+
+ it("[[Call]] only gets the value once", () => {
+ const get1 = spy(() => true);
+ findLastItem({
+ get 1() {
+ return get1();
+ },
+ length: 2,
+ }, ($) => $);
+ assertSpyCalls(get1, 1);
+ });
+
+ it("[[Call]] passes the value, index, and this value to the callback", () => {
+ const arr = ["success", "success", "failure", ,];
+ const callback = spy(($) => $ === "success");
+ const thisArg = {};
+ findLastItem(arr, callback, thisArg);
+ assertSpyCalls(callback, 2);
+ assertSpyCall(callback, 0, {
+ args: ["failure", 2, arr],
+ self: thisArg,
+ });
+ assertSpyCall(callback, 1, {
+ args: ["success", 1, arr],
+ self: thisArg,
+ });
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new findLastItem([], () => {}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(findLastItem.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(findLastItem.name, "findLastItem");
+ });
+ });
+});
+
+describe("flatmap", () => {
+ it("[[Call]] flatmaps", () => {
+ assertEquals(
+ flatmap([, "a", ["b"], [["c"]]], ($) => $),
+ ["a", "b", ["c"]],
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new flatmap([], () => {}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(flatmap.length, 2);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(flatmap.name, "flatmap");
+ });
});
});
});
});
-describe("isConcatSpreadable", () => {
- it("[[Call]] returns false for primitives", () => {
- assertStrictEquals(isConcatSpreadable("failure"), false);
- });
-
- it("[[Call]] returns false if [Symbol.isConcatSpreadable] is null or false", () => {
- assertStrictEquals(
- isConcatSpreadable(
- Object.assign([], { [Symbol.isConcatSpreadable]: null }),
- ),
- false,
- );
- assertStrictEquals(
- isConcatSpreadable(
- Object.assign([], { [Symbol.isConcatSpreadable]: false }),
- ),
- false,
- );
- });
-
- it("[[Call]] returns true if [Symbol.isConcatSpreadable] is undefined and the object is an array", () => {
- assertStrictEquals(
- isConcatSpreadable(
- Object.assign([], { [Symbol.isConcatSpreadable]: undefined }),
- ),
- true,
- );
- });
-
- it("[[Call]] returns true if [Symbol.isConcatSpreadable] is true", () => {
+describe("isDenseProxy", () => {
+ it("[[Call]] returns true for dense proxies", () => {
+ const underlying = [];
+ const proxy = denseProxy(underlying);
assertStrictEquals(
- isConcatSpreadable({ [Symbol.isConcatSpreadable]: true }),
+ isDenseProxy(proxy),
true,
);
});
-});
-
-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);
+ it("[[Call]] returns false for others", () => {
assertStrictEquals(
- isIntegerIndexString("9007199254740993"),
+ isDenseProxy([]),
false,
);
});
- 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("[[Construct]] throws an error", () => {
+ assertThrows(() => new isDenseProxy([]));
});
- it("[[Call]] returns false for numbers greater than or equal to 2 ** 53", () => {
- assertStrictEquals(
- isIntegerIndexString("9007199254740992"),
- false,
- );
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ assertStrictEquals(isDenseProxy.length, 1);
+ });
});
- it("[[Call]] returns true for safe canonical integer strings", () => {
- assertStrictEquals(isIntegerIndexString("0"), true);
- assertStrictEquals(isIntegerIndexString("9007199254740991"), true);
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ assertStrictEquals(isDenseProxy.name, "isDenseProxy");
+ });
});
});
-describe("lengthOfArrayLike", () => {
- it("[[Call]] returns the length", () => {
- assertStrictEquals(
- lengthOfArrayLike({ length: 9007199254740991 }),
- 9007199254740991,
- );
- });
-
- it("[[Call]] returns a non·nan result", () => {
- assertStrictEquals(lengthOfArrayLike({ length: NaN }), 0);
- assertStrictEquals(lengthOfArrayLike({ length: "failure" }), 0);
- });
-
- it("[[Call]] returns an integral result", () => {
- assertStrictEquals(lengthOfArrayLike({ length: 0.25 }), 0);
- assertStrictEquals(lengthOfArrayLike({ length: 1.1 }), 1);
- });
-
- it("[[Call]] returns a result greater than or equal to zero", () => {
- assertStrictEquals(lengthOfArrayLike({ length: -0 }), 0);
- assertStrictEquals(lengthOfArrayLike({ length: -1 }), 0);
- assertStrictEquals(lengthOfArrayLike({ length: -Infinity }), 0);
- });
-
- it("[[Call]] returns a result less than 2 ** 53", () => {
- assertStrictEquals(
- lengthOfArrayLike({ length: 9007199254740992 }),
- 9007199254740991,
- );
- assertStrictEquals(
- lengthOfArrayLike({ length: Infinity }),
- 9007199254740991,
+describe("toArray", () => {
+ it("[[Call]] returns an array of the values in a provided arraylike", () => {
+ assertEquals(
+ toArray({ 1: "success", length: 3 }),
+ [, "success", ,],
);
});
});
-describe("toIndex", () => {
- it("[[Call]] returns an index", () => {
- assertStrictEquals(toIndex(9007199254740991), 9007199254740991);
- });
-
- it("[[Call]] returns zero for a zerolike result", () => {
- 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));
- });
-});
-
-describe("toLength", () => {
- it("[[Call]] returns a length", () => {
- assertStrictEquals(toLength(9007199254740991), 9007199254740991);
- });
-
- it("[[Call]] returns a non·nan result", () => {
- assertStrictEquals(toLength(NaN), 0);
- assertStrictEquals(toLength("failure"), 0);
- });
-
- it("[[Call]] returns an integral result", () => {
- 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);
+describe("toDenseArray", () => {
+ it("[[Call]] returns a dense array of the values in a provided arraylike", () => {
+ assertEquals(
+ toDenseArray({ 1: "success", length: 3 }),
+ [undefined, "success", undefined],
+ );
});
});