123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- /**
- * Like `Array#splice`, but smarter for giant arrays.
- *
- * `Array#splice` takes all items to be inserted as individual argument which
- * causes a stack overflow in V8 when trying to insert 100k items for instance.
- *
- * Otherwise, this does not return the removed items, and takes `items` as an
- * array instead of rest parameters.
- *
- * @template {unknown} T
- * Item type.
- * @param {Array<T>} list
- * List to operate on.
- * @param {number} start
- * Index to remove/insert at (can be negative).
- * @param {number} remove
- * Number of items to remove.
- * @param {Array<T>} items
- * Items to inject into `list`.
- * @returns {undefined}
- * Nothing.
- */
- export function splice(list, start, remove, items) {
- const end = list.length
- let chunkStart = 0
- /** @type {Array<unknown>} */
- let parameters
- // Make start between zero and `end` (included).
- if (start < 0) {
- start = -start > end ? 0 : end + start
- } else {
- start = start > end ? end : start
- }
- remove = remove > 0 ? remove : 0
- // No need to chunk the items if there’s only a couple (10k) items.
- if (items.length < 10000) {
- parameters = Array.from(items)
- parameters.unshift(start, remove)
- // @ts-expect-error Hush, it’s fine.
- list.splice(...parameters)
- } else {
- // Delete `remove` items starting from `start`
- if (remove) list.splice(start, remove)
- // Insert the items in chunks to not cause stack overflows.
- while (chunkStart < items.length) {
- parameters = items.slice(chunkStart, chunkStart + 10000)
- parameters.unshift(start, 0)
- // @ts-expect-error Hush, it’s fine.
- list.splice(...parameters)
- chunkStart += 10000
- start += 10000
- }
- }
- }
- /**
- * Append `items` (an array) at the end of `list` (another array).
- * When `list` was empty, returns `items` instead.
- *
- * This prevents a potentially expensive operation when `list` is empty,
- * and adds items in batches to prevent V8 from hanging.
- *
- * @template {unknown} T
- * Item type.
- * @param {Array<T>} list
- * List to operate on.
- * @param {Array<T>} items
- * Items to add to `list`.
- * @returns {Array<T>}
- * Either `list` or `items`.
- */
- export function push(list, items) {
- if (list.length > 0) {
- splice(list, list.length, 0, items)
- return list
- }
- return items
- }
|