1 // ♓🌟 Piscēs ∷ collection.js
2 // ====================================================================
4 // Copyright © 2020–2023 Lady [@ Lady’s Computer].
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
10 import { call
, createCallableFunction
} from "./function.js";
13 MAXIMUM_SAFE_INTEGRAL_NUMBER
,
14 } from "./numeric.js";
16 canonicalNumericIndexString
,
24 const { prototype: arrayPrototype
} = Array
;
27 /** Returns an array of the provided values. */
30 /** Returns whether the provided value is an array. */
33 /** Returns an array created from the provided arraylike. */
38 * Returns the result of catenating the provided arraylikes into a new
39 * collection according to the algorithm of `Array::concat`.
41 export const catenate
= createCallableFunction(
42 arrayPrototype
.concat
,
47 * Copies the items in the provided object to a new location according
48 * to the algorithm of `Array::copyWithin`.
50 export const copyWithin
= createCallableFunction(
51 arrayPrototype
.copyWithin
,
55 * Fills the provided object with the provided value according to the
56 * algorithm of `Array::fill`.
58 export const fill
= createCallableFunction(arrayPrototype
.fill
);
61 * Returns the result of filtering the provided object with the
62 * provided callback, according to the algorithm of `Array::filter`.
64 export const filter
= createCallableFunction(arrayPrototype
.filter
);
67 * Returns the first index in the provided object whose value satisfies
68 * the provided callback according to the algorithm of
71 export const findIndex
= createCallableFunction(
72 arrayPrototype
.findIndex
,
76 * Returns the first indexed entry in the provided object whose value
77 * satisfies the provided callback.
79 * If a third argument is supplied, it will be used as the this value
82 export const findIndexedEntry
= (
87 let result
= undefined;
88 findItem($, (kValue
, k
, O
) => {
89 if (call(callback
, thisArg
, [kValue
, k
, O
])) {
90 // The callback succeeded.
94 // The callback failed.
102 * Returns the first indexed value in the provided object which
103 * satisfies the provided callback, according to the algorithm of
106 export const findItem
= createCallableFunction(
112 * Returns the result of flatmapping the provided value with the
113 * provided callback according to the algorithm of `Array::flatMap`.
115 export const flatmap
= createCallableFunction(
116 arrayPrototype
.flatMap
,
121 * Returns the result of flattening the provided object according to
122 * the algorithm of `Array::flat`.
124 export const flatten
= createCallableFunction(
130 * Returns the first index of the provided object with a value
131 * equivalent to the provided value according to the algorithm of
134 export const getFirstIndex
= createCallableFunction(
135 arrayPrototype
.indexOf
,
140 * Returns the item on the provided object at the provided index
141 * according to the algorithm of `Array::at`.
143 export const getItem
= createCallableFunction(
149 * Returns the last index of the provided object with a value
150 * equivalent to the provided value according to the algorithm of
151 * `Array::lastIndexOf`.
153 export const getLastIndex
= createCallableFunction(
154 arrayPrototype
.lastIndexOf
,
159 * Returns whether every indexed value in the provided object satisfies
160 * the provided function, according to the algorithm of `Array::every`.
162 export const hasEvery
= createCallableFunction(
163 arrayPrototype
.every
,
168 * Returns whether the provided object has an indexed value which
169 * satisfies the provided function, according to the algorithm of
172 export const hasSome
= createCallableFunction(
178 * Returns whether the provided object has an indexed value equivalent
179 * to the provided value according to the algorithm of
182 * ※ This algorithm treats missing values as `undefined` rather than
185 export const includes
= createCallableFunction(
186 arrayPrototype
.includes
,
190 * Returns an iterator over the indexed entries in the provided value
191 * according to the algorithm of `Array::entries`.
193 export const indexedEntries
= createCallableFunction(
194 arrayPrototype
.entries
,
199 * Returns an iterator over the indices in the provided value according
200 * to the algorithm of `Array::keys`.
202 export const indices
= createCallableFunction(
207 /** Returns whether the provided value is an array index string. */
208 export const isArrayIndexString
= ($) => {
209 const value
= canonicalNumericIndexString($);
210 if (value
!== undefined) {
211 // The provided value is a canonical numeric index string.
212 return sameValue(value
, 0) || value
> 0 && value
< -1 >>> 0 &&
213 value
=== toLength(value
);
215 // The provided value is not a canonical numeric index string.
220 /** Returns whether the provided value is arraylike. */
221 export const isArraylikeObject
= ($) => {
222 if (type($) !== "object") {
226 lengthOfArraylike($); // throws if not arraylike
235 * Returns whether the provided object is a collection.
237 * The definition of “collection” used by Piscēs is similar to
238 * Ecmascript’s definition of an arraylike object, but it differs in
241 * - It requires the provided value to be a proper object.
243 * - It requires the `length` property to be an integer index.
245 * - It requires the object to be concat‐spreadable, meaning it must
246 * either be an array or have `.[Symbol.isConcatSpreadable]` be true.
248 export const isCollection
= ($) => {
249 if (!(type($) === "object" && "length" in $)) {
250 // The provided value is not an object or does not have a `length`.
254 toIndex($.length
); // will throw if `length` is not an index
255 return isConcatSpreadable($);
263 * Returns whether the provided value is spreadable during array
266 * This is also used to determine which things should be treated as
269 export const isConcatSpreadable
= ($) => {
270 if (type($) !== "object") {
271 // The provided value is not an object.
274 // The provided value is an object.
275 const spreadable
= $[Symbol
.isConcatSpreadable
];
276 return spreadable
!== undefined ? !!spreadable
: isArray($);
280 /** Returns whether the provided value is an integer index string. */
281 export const isIntegerIndexString
= ($) => {
282 const value
= canonicalNumericIndexString($);
283 if (value
!== undefined && isIntegralNumber(value
)) {
284 // The provided value is a canonical numeric index string.
285 return sameValue(value
, 0) ||
286 value
> 0 && value
<= MAXIMUM_SAFE_INTEGRAL_NUMBER
&&
287 value
=== toLength(value
);
289 // The provided value is not a canonical numeric index string.
295 * Returns an iterator over the items in the provided value according
296 * to the algorithm of `Array::values`.
298 export const items
= createCallableFunction(
299 arrayPrototype
.values
,
304 * Returns the result of mapping the provided value with the provided
305 * callback according to the algorithm of `Array::map`.
307 export const map
= createCallableFunction(arrayPrototype
.map
);
310 * Pops from the provided value according to the algorithm of
313 export const pop
= createCallableFunction(arrayPrototype
.pop
);
316 * Pushes onto the provided value according to the algorithm of
319 export const push
= createCallableFunction(arrayPrototype
.push
);
322 * Returns the result of reducing the provided value with the provided
323 * callback, according to the algorithm of `Array::reduce`.
325 export const reduce
= createCallableFunction(arrayPrototype
.reduce
);
328 * Reverses the provided value according to the algorithm of
331 export const reverse
= createCallableFunction(arrayPrototype
.reverse
);
334 * Shifts the provided value according to the algorithm of
337 export const shift
= createCallableFunction(arrayPrototype
.shift
);
340 * Returns a slice of the provided value according to the algorithm of
343 export const slice
= createCallableFunction(arrayPrototype
.slice
);
346 * Sorts the provided value in‐place according to the algorithm of
349 export const sort
= createCallableFunction(arrayPrototype
.sort
);
352 * Splices into and out of the provided value according to the
353 * algorithm of `Array::splice`.
355 export const splice
= createCallableFunction(arrayPrototype
.splice
);
358 * Unshifts the provided value according to the algorithm of
361 export const unshift
= createCallableFunction(arrayPrototype
.unshift
);