UNPKG

@solid/community-server

Version:

Community Solid Server: an open and modular implementation of the Solid specifications

180 lines 6.14 kB
"use strict"; // Utility functions for iterables that avoid array conversion Object.defineProperty(exports, "__esModule", { value: true }); exports.map = map; exports.filter = filter; exports.concat = concat; exports.find = find; exports.reduce = reduce; exports.sortedAsyncMerge = sortedAsyncMerge; exports.asyncToArray = asyncToArray; /** * Creates a new iterable with the results of calling a provided function on every element in the calling array. * Similar to the {@link Array.prototype.map} function. * See the documentation of the above function for more details. * * @param iterable - Iterable on which to call the map function. * @param callbackFn - Function that is called for every element. * @param thisArg - Value to use as `this` when executing `callbackFn`. */ function* map(iterable, callbackFn, thisArg) { const boundMapFn = callbackFn.bind(thisArg); let count = 0; for (const value of iterable) { yield boundMapFn(value, count); count += 1; } } /** * Creates a new iterable with all elements that pass the test implemented by the provided function. * Similar to the {@link Array.prototype.filter} function. * See the documentation of the above function for more details. * * @param iterable - Iterable on which to call the map function. * @param callbackFn - Function that is called to test every element. * @param thisArg - Value to use as `this` when executing `callbackFn`. */ function* filter(iterable, callbackFn, thisArg) { const boundFilterFn = callbackFn.bind(thisArg); let count = 0; for (const value of iterable) { if (boundFilterFn(value, count)) { yield value; } count += 1; } } /** * Creates a new iterable that is a concatenation of all the iterables in the input. * * @param iterables - An iterable of which the contents will be concatenated into a new iterable. */ function* concat(iterables) { for (const iterable of iterables) { yield* iterable; } } /** * Returns the first element in the provided iterable that satisfies the provided testing function. * If no values satisfy the testing function, `undefined` is returned. * Similar to the {@link Array.prototype.find} function. * See the documentation of the above function for more details. * * @param iterable - Iterable on which to call the map function. * @param callbackFn - Function that is called to test every element. * @param thisArg - Value to use as `this` when executing `callbackFn`. */ function find(iterable, callbackFn, thisArg) { const boundMapFn = callbackFn.bind(thisArg); const count = 0; for (const value of iterable) { if (boundMapFn(value, count)) { return value; } } } function reduce(iterable, callbackFn, initialValue) { const iterator = iterable[Symbol.iterator](); let count = 0; if (!initialValue) { const next = iterator.next(); if (next.done) { throw new TypeError('Iterable is empty and no initial value was provided.'); } // `initialValue` being undefined means the first signature was used where TIn === TOut initialValue = next.value; count += 1; } let previousValue = initialValue; let next = iterator.next(); while (!next.done) { previousValue = callbackFn(previousValue, next.value, count); next = iterator.next(); count += 1; } return previousValue; } /** * Helper function for {@link sortedAsyncMerge}. * * Returns the next result of an AsyncIterator, or undefined if the iterator is finished. */ async function nextAsyncEntry(iterator) { const result = await iterator.next(); if (result.done) { return; } return result.value; } /** * Helper function for {@link sortedAsyncMerge}. * * Compares the next results of all `iterators` and returns the first one, * determined by the provided `comparator`. * * `results` should contain the first result of all these iterators. * This array will also be updated, replacing the result of the iterator whose result was chosen by the next one. */ async function findNextSorted(iterators, results, comparator) { let best; // For every iterator: see if their next result is the best one so far for (let i = 0; i < iterators.length; ++i) { const value = results[i]; if (typeof value !== 'undefined') { let compare = 1; if (best) { compare = comparator(best.value, value); } if (compare > 0) { best = { idx: i, value }; } } } if (best) { // Advance the iterator that returned the new result results[best.idx] = await nextAsyncEntry(iterators[best.idx]); } // Will return undefined if `best` was never initialized above return best?.value; } /** * Merges the results of several sorted iterators. * In case the results of the individual iterators are not sorted the outcome results will also not be sorted. * * @param iterators - The iterators whose results need to be merged. * @param comparator - The comparator to use to compare the results. */ async function* sortedAsyncMerge(iterators, comparator) { if (!comparator) { comparator = (left, right) => { if (left < right) { return -1; } return left > right ? 1 : 0; }; } // Initialize the array to the first result of every iterator const results = []; for (const iterator of iterators) { results.push(await nextAsyncEntry(iterator)); } // Keep returning results as long as we find them while (true) { const next = await findNextSorted(iterators, results, comparator); if (typeof next === 'undefined') { return; } yield next; } } /** * Converts an `AsyncIterator` to an array. */ async function asyncToArray(iterable) { const arr = []; for await (const result of iterable) { arr.push(result); } return arr; } //# sourceMappingURL=IterableUtil.js.map