X-Git-Url: https://git.ladys.computer/Pisces/blobdiff_plain/58d78d7c0602b17a9599e28232cc8a2ff1d8fc65..refs/heads/current:/collection.js?ds=sidebyside diff --git a/collection.js b/collection.js index 3cfe938..d340709 100644 --- a/collection.js +++ b/collection.js @@ -7,16 +7,9 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at . -import { call, makeCallable } from "./function.js"; -import { - floor, - isIntegralNumber, - isNan, - max, - MAXIMUM_SAFE_INTEGRAL_NUMBER, - min, -} from "./numeric.js"; -import { sameValue, type } from "./value.js"; +import { call, createCallableFunction } from "./function.js"; +import { isConcatSpreadableObject } from "./object.js"; +import { toIndex, type } from "./value.js"; const { prototype: arrayPrototype } = Array; @@ -31,55 +24,43 @@ export const { from: toArray, } = Array; -/** - * Returns −0 if the provided argument is "-0"; returns a number - * representing the index if the provided argument is a canonical - * numeric index string; otherwise, returns undefined. - * - * There is no clamping of the numeric index, but note that numbers - * above 2^53 − 1 are not safe nor valid integer indices. - */ -export const canonicalNumericIndexString = ($) => { - if (typeof $ !== "string") { - return undefined; - } else if ($ === "-0") { - return -0; - } else { - const n = +$; - return $ === `${n}` ? n : undefined; - } -}; - /** * Returns the result of catenating the provided arraylikes into a new * collection according to the algorithm of `Array::concat`. */ -export const catenate = makeCallable(arrayPrototype.concat); +export const catenate = createCallableFunction( + arrayPrototype.concat, + "catenate", +); /** * Copies the items in the provided object to a new location according * to the algorithm of `Array::copyWithin`. */ -export const copyWithin = makeCallable(arrayPrototype.copyWithin); +export const copyWithin = createCallableFunction( + arrayPrototype.copyWithin, +); /** * Fills the provided object with the provided value according to the * algorithm of `Array::fill`. */ -export const fill = makeCallable(arrayPrototype.fill); +export const fill = createCallableFunction(arrayPrototype.fill); /** * Returns the result of filtering the provided object with the * provided callback, according to the algorithm of `Array::filter`. */ -export const filter = makeCallable(arrayPrototype.filter); +export const filter = createCallableFunction(arrayPrototype.filter); /** * Returns the first index in the provided object whose value satisfies * the provided callback according to the algorithm of * `Array::findIndex`. */ -export const findIndex = makeCallable(arrayPrototype.findIndex); +export const findIndex = createCallableFunction( + arrayPrototype.findIndex, +); /** * Returns the first indexed entry in the provided object whose value @@ -112,52 +93,76 @@ export const findIndexedEntry = ( * satisfies the provided callback, according to the algorithm of * `Array::find`. */ -export const findItem = makeCallable(arrayPrototype.find); +export const findItem = createCallableFunction( + arrayPrototype.find, + "findItem", +); /** * Returns the result of flatmapping the provided value with the * provided callback according to the algorithm of `Array::flatMap`. */ -export const flatmap = makeCallable(arrayPrototype.flatMap); +export const flatmap = createCallableFunction( + arrayPrototype.flatMap, + "flatmap", +); /** * Returns the result of flattening the provided object according to * the algorithm of `Array::flat`. */ -export const flatten = makeCallable(arrayPrototype.flat); +export const flatten = createCallableFunction( + arrayPrototype.flat, + "flatten", +); /** * Returns the first index of the provided object with a value * equivalent to the provided value according to the algorithm of * `Array::indexOf`. */ -export const getFirstIndex = makeCallable(arrayPrototype.indexOf); +export const getFirstIndex = createCallableFunction( + arrayPrototype.indexOf, + "getFirstIndex", +); /** * Returns the item on the provided object at the provided index * according to the algorithm of `Array::at`. */ -export const getItem = makeCallable(arrayPrototype.at); +export const getItem = createCallableFunction( + arrayPrototype.at, + "getItem", +); /** * Returns the last index of the provided object with a value * equivalent to the provided value according to the algorithm of * `Array::lastIndexOf`. */ -export const getLastIndex = makeCallable(arrayPrototype.lastIndexOf); +export const getLastIndex = createCallableFunction( + arrayPrototype.lastIndexOf, + "getLastIndex", +); /** * Returns whether every indexed value in the provided object satisfies * the provided function, according to the algorithm of `Array::every`. */ -export const hasEvery = makeCallable(arrayPrototype.every); +export const hasEvery = createCallableFunction( + arrayPrototype.every, + "hasEvery", +); /** * Returns whether the provided object has an indexed value which * satisfies the provided function, according to the algorithm of * `Array::some`. */ -export const hasSome = makeCallable(arrayPrototype.some); +export const hasSome = createCallableFunction( + arrayPrototype.some, + "hasSome", +); /** * Returns whether the provided object has an indexed value equivalent @@ -167,46 +172,27 @@ export const hasSome = makeCallable(arrayPrototype.some); * ※ This algorithm treats missing values as `undefined` rather than * skipping them. */ -export const includes = makeCallable(arrayPrototype.includes); +export const includes = createCallableFunction( + arrayPrototype.includes, +); /** * Returns an iterator over the indexed entries in the provided value * according to the algorithm of `Array::entries`. */ -export const indexedEntries = makeCallable(arrayPrototype.entries); +export const indexedEntries = createCallableFunction( + arrayPrototype.entries, + "indexedEntries", +); /** * Returns an iterator over the indices in the provided value according * to the algorithm of `Array::keys`. */ -export const indices = makeCallable(arrayPrototype.keys); - -/** Returns whether the provided value is an array index string. */ -export const isArrayIndexString = ($) => { - const value = canonicalNumericIndexString($); - if (value !== undefined) { - // The provided value is a canonical numeric index string. - return sameValue(value, 0) || value > 0 && value < -1 >>> 0 && - value === toLength(value); - } else { - // The provided value is not a canonical numeric index string. - return false; - } -}; - -/** Returns whether the provided value is arraylike. */ -export const isArraylikeObject = ($) => { - if (type($) !== "object") { - return false; - } else { - try { - lengthOfArraylike($); // throws if not arraylike - return true; - } catch { - return false; - } - } -}; +export const indices = createCallableFunction( + arrayPrototype.keys, + "indices", +); /** * Returns whether the provided object is a collection. @@ -229,147 +215,78 @@ export const isCollection = ($) => { } else { try { toIndex($.length); // will throw if `length` is not an index - return isConcatSpreadable($); + return isConcatSpreadableObject($); } catch { return false; } } }; -/** - * Returns whether the provided value is spreadable during array - * concatenation. - * - * This is also used to determine which things should be treated as - * collections. - */ -export const isConcatSpreadable = ($) => { - if (type($) !== "object") { - // The provided value is not an object. - return false; - } else { - // The provided value is an object. - const spreadable = $[Symbol.isConcatSpreadable]; - return spreadable !== undefined ? !!spreadable : isArray($); - } -}; - -/** Returns whether the provided value is an integer index string. */ -export const isIntegerIndexString = ($) => { - const value = canonicalNumericIndexString($); - if (value !== undefined && isIntegralNumber(value)) { - // The provided value is a canonical numeric index string. - return sameValue(value, 0) || - value > 0 && value <= MAXIMUM_SAFE_INTEGRAL_NUMBER && - value === toLength(value); - } else { - // The provided value is not a canonical numeric index string. - return false; - } -}; - /** * Returns an iterator over the items in the provided value according * to the algorithm of `Array::values`. */ -export const items = makeCallable(arrayPrototype.values); - -/** - * Returns the length of the provided arraylike object. - * - * Will throw if the provided object is not arraylike. - * - * This can produce larger lengths than can actually be stored in - * arrays, because no such restrictions exist on arraylike methods. - */ -export const lengthOfArraylike = ({ length }) => toLength(length); +export const items = createCallableFunction( + arrayPrototype.values, + "items", +); /** * Returns the result of mapping the provided value with the provided * callback according to the algorithm of `Array::map`. */ -export const map = makeCallable(arrayPrototype.map); +export const map = createCallableFunction(arrayPrototype.map); /** * Pops from the provided value according to the algorithm of * `Array::pop`. */ -export const pop = makeCallable(arrayPrototype.pop); +export const pop = createCallableFunction(arrayPrototype.pop); /** * Pushes onto the provided value according to the algorithm of * `Array::push`. */ -export const push = makeCallable(arrayPrototype.push); +export const push = createCallableFunction(arrayPrototype.push); /** * Returns the result of reducing the provided value with the provided * callback, according to the algorithm of `Array::reduce`. */ -export const reduce = makeCallable(arrayPrototype.reduce); +export const reduce = createCallableFunction(arrayPrototype.reduce); /** * Reverses the provided value according to the algorithm of * `Array::reverse`. */ -export const reverse = makeCallable(arrayPrototype.reverse); +export const reverse = createCallableFunction(arrayPrototype.reverse); /** * Shifts the provided value according to the algorithm of * `Array::shift`. */ -export const shift = makeCallable(arrayPrototype.shift); +export const shift = createCallableFunction(arrayPrototype.shift); /** * Returns a slice of the provided value according to the algorithm of * `Array::slice`. */ -export const slice = makeCallable(arrayPrototype.slice); +export const slice = createCallableFunction(arrayPrototype.slice); /** * Sorts the provided value in‐place according to the algorithm of * `Array::sort`. */ -export const sort = makeCallable(arrayPrototype.sort); +export const sort = createCallableFunction(arrayPrototype.sort); /** * Splices into and out of the provided value according to the * algorithm of `Array::splice`. */ -export const splice = makeCallable(arrayPrototype.splice); - -/** - * Returns the result of converting the provided value to an array - * index, or throws an error if it is out of range. - */ -export const toIndex = ($) => { - const integer = floor($); - if (isNan(integer) || integer == 0) { - // The value is zero·like. - return 0; - } else { - // The value is not zero·like. - const clamped = toLength(integer); - if (clamped !== integer) { - // Clamping the value changes it. - throw new RangeError(`Piscēs: Index out of range: ${$}.`); - } else { - // The value is within appropriate bounds. - return integer; - } - } -}; - -/** Returns the result of converting the provided value to a length. */ -export const toLength = ($) => { - const len = floor($); - return isNan(len) || len == 0 - ? 0 - : max(min(len, MAXIMUM_SAFE_INTEGRAL_NUMBER), 0); -}; +export const splice = createCallableFunction(arrayPrototype.splice); /** * Unshifts the provided value according to the algorithm of * `Array::unshift`. */ -export const unshift = makeCallable(arrayPrototype.unshift); +export const unshift = createCallableFunction(arrayPrototype.unshift);