// 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 { 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;
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
* 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
* ※ 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.
} 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);