• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16package escompat;
17
18// NOTE: autogenerated file
19
20function asIntOrDefault(n: Number | undefined, def: int): int {
21    if (__runtimeIsSameReference(n, undefined)) {
22        return def
23    }
24    return (n! as Object as Number) as number as int;
25}
26
27function normalizeIndex(idx: int, len: int): int {
28    if (idx < -len) {
29        return 0
30    }
31    if (idx < 0) {
32        return len + idx
33    }
34    if (idx > len) {
35        return len
36    }
37    return idx
38}
39
40class ArrayKeysIterator<T> implements IterableIterator<number> {
41    private parent: Array<T>
42    private idx: int = 0
43
44    constructor(parent: Array<T>) {
45        this.parent = parent
46    }
47
48    override next(): IteratorResult<number> {
49        if (this.idx >= this.parent.actualLength) {
50            return new IteratorResult<number>()
51        }
52        return new IteratorResult<number>(this.idx++ as number)
53    }
54
55    override $_iterator(): IterableIterator<number> {
56        return this
57    }
58}
59
60class FromBuffer {}
61const FROM_BUFFER = new FromBuffer()
62
63/**
64 * Represents JS API-compatible Array
65 */
66export class Array<T> implements ReadonlyArray<T>, Iterable<T> {
67    private buffer: NullishType[]
68    internal actualLength: int
69
70    override get length(): number {
71        return this.actualLength as number
72    }
73
74    set length(newLen: number): void {
75        const len = newLen as int
76        if (len < 0 || len > this.actualLength) {
77            throw new RangeError("can't change length to bigger or negative")
78        }
79        this.actualLength = len
80    }
81
82    public override $_get(index: number): T {
83        return this.$_get(index as int)
84    }
85
86    public $_set(i: number, val: T): void {
87        this.$_set(i as int, val)
88    }
89
90    public $_get(idx: int): T {
91        if (idx >= this.actualLength || idx < 0) {
92            throw new RangeError("Out of bounds")
93        }
94        return this.buffer[idx] as T
95    }
96
97    internal $_get_unsafe(idx: int): T {
98        return this.buffer[idx] as T
99    }
100
101    public $_set(idx: int, val: T): void {
102        if (idx >= this.actualLength) {
103            throw new RangeError("Out of bounds")
104        }
105        this.buffer[idx] = val as Object
106    }
107
108    private $_set_unsafe(idx: int, val: T): void {
109        this.buffer[idx] = val
110    }
111
112    /**
113     * Creates a new instance of Array
114     */
115    public constructor(arrayLen: int) {
116        this.buffer = new NullishType[arrayLen]
117        this.actualLength = arrayLen
118    }
119
120    public constructor(arrayLen: number) {
121        this(arrayLen as int)
122    }
123
124    internal constructor(_tag: FromBuffer, buf: NullishType[]) {
125        this.buffer = buf
126        this.actualLength = buf.length
127    }
128
129    internal constructor() {
130        this.buffer = new NullishType[4]
131        this.actualLength = 0
132    }
133
134    /**
135     * Creates a new instance of Array based on Object[]
136     *
137     * @param d Array initializer
138     */
139    public constructor(first: T, ...d: T[]) {
140        this.buffer = new NullishType[d.length + 1]
141        this.actualLength = d.length + 1
142
143        this.buffer[0] = first
144
145        for (let k: int = 0; k < d.length; k++) {
146            this.$_set_unsafe(k + 1, d[k])
147        }
148    }
149
150    /**
151     * Creates a new instance of an Array with the specified length
152     *
153     * @param arrayLength The length of the array to be created (optional).
154     *
155     * @returns A new Array instance with the specified length
156     */
157    static invoke<T>(arrayLength?: number): Array<T> {
158        if (arrayLength != undefined) {
159            return new Array<T>(arrayLength);
160        } else {
161            return new Array<T>();
162        }
163    }
164
165    /**
166     * Creates a new `Array` instance from `Object[]` primitive array.
167     *
168     * @param arr an iterable object to convert to an array.
169     *
170     * @returns `Array` intance constructed from `Object[]` primitive array.
171     */
172    public static from<T>(iterable: ArrayLike<T> | Iterable<T>): Array<T> {
173        return Array.from<T, T>(iterable, (x: T, k: number): T => x)
174    }
175
176    /**
177     * Creates a new `Array` instance from `Object[]` primitive array.
178     *
179     * @param iterable an iterable object to convert to an array.
180     *
181     * @param mapfn a mapping function to call on every element of the array.
182     * Every value to be added to the array is first passed through this function, and `mapfn`'s return value
183     * is added to the array instead.
184     *
185     * @returns `Array` intance constructed from `Object[]` primitive array and given function.
186     */
187    public static from<T, U>(iterable: ArrayLike<T> | Iterable<T>, mapfn: (v: T, k: number) => U): Array<U> {
188        const ret = new Array<U>()
189        // NOTE (ikorobkov): Please don't replace idx as int[1] with int-variable, because of value of single variable doesn't change (idx++) into lambda call by unknown reason
190        const idx = new int[1]
191        idx[0] = 0
192        iteratorForEach<T>(iterable.$_iterator(), (x: T): void => {
193            ret.push(mapfn(x, idx[0] as number))
194            idx[0] += 1
195        })
196        return ret
197    }
198
199    /**
200    * Creates a new `Array` instance from `Object[]` primitive array.
201    *
202    * @param arr primitive array.
203    *
204    * @returns `Array` intance constructed from `Object[]` primitive array.
205    */
206    public static from<T>(arr: T[]): Array<T> {
207        const len = arr.length
208        const ret = new NullishType[len as int]
209        for (let i: int = 0; i < len; i++) {
210            ret[i] = arr[i] as NullishType
211        }
212        return new Array<T>(FROM_BUFFER, ret)
213    }
214
215    /**
216     * Default comparison function for sort algorithm.
217     * Objects are compared as string. Both objects are convereted to string
218     * using `toString()` method and compared using `compareTo() method of `string` class.
219     *
220     * @param a: Object - Object to be compared
221     *
222     * @param b: Object - Object to be compared
223     *
224     * @returns Returns one of values -1, 0, 1 (_less_, _equal_, _greater_ respectively).
225     */
226    private static defaultComparator(a: NullishType, b: NullishType): number {
227        if (a instanceof Number && b instanceof Number) {
228            const x = (a as Number).valueOf()
229            const y = (b as Number).valueOf()
230            if (Number.isInteger(x) && Number.isInteger(y) &&
231                x <= Int.MAX_VALUE / 128 && x >= Int.MIN_VALUE / 128 &&
232                y <= Int.MAX_VALUE / 128 && y >= Int.MIN_VALUE / 128) {
233                let z = x as int
234                let w = y as int
235                return Array.defaultComparatorInts(z, w)
236            }
237        } else if (a instanceof String && b instanceof String) {
238            return a.compareTo(b)
239        }
240        let sa = new String(a)
241        let sb = new String(b)
242        return sa.compareTo(sb)
243    }
244
245    private static defaultComparatorInts(a: int, b: int): number {
246        if (a < 0) {
247            if (b >= 0) {
248                return -1
249            }
250            a *= -1
251            b *= -1
252        } else if (b < 0) {
253            return 1
254        }
255        let aDigs = 1
256        while (10 * aDigs <= a) {
257            aDigs *= 10
258        }
259        let bDigs = 1
260        while (10 * bDigs <= b) {
261            bDigs *= 10
262        }
263
264        while (aDigs > 0 && bDigs > 0) {
265            let r = (a / aDigs) - (b / bDigs)
266            if (r != 0) {
267                return r
268            }
269            aDigs /= 10
270            bDigs /= 10
271        }
272        return (aDigs - bDigs)
273    }
274
275    private static defaultComparatorStr(a: String, b: String) {
276        return a.compareTo(b)
277    }
278
279    /**
280     * Helper function preparing copy of `this` instance of `Array` class' data array.
281     *
282     * @returns Copy of an `Array`'s primitive array data.
283     */
284    private copyArray(): NullishType[] {
285        let len: int = this.actualLength
286        let res = new NullishType[len]
287        for (let i = 0; i < len; i++) {
288            res[i] = this.$_get_unsafe(i)
289        }
290        return res
291    }
292
293    private wrap_default_sort(): void {
294        let idxNonUndef = 0
295        type arrType = String | null
296        try {
297            let strArr = new arrType[this.actualLength]
298            for (let i = 0; i < this.actualLength; i++) {
299                const vl = this.$_get_unsafe(i)
300                // NOTE(aleksander-sotov) We can't use === to compare with undefined due to 18518
301                if (!__runtimeIsSameReference(vl, undefined)) {
302                    if (vl == null) {
303                        this.$_set_unsafe(idxNonUndef, vl as T)
304                        strArr[idxNonUndef] = "null"
305                    } else {
306                        this.$_set_unsafe(idxNonUndef, vl)
307                        strArr[idxNonUndef] = vl.toString()
308                    }
309                    idxNonUndef++
310                }
311            }
312            let sortTo = idxNonUndef
313            for (let i = idxNonUndef; i < this.actualLength; i++) {
314                this.$_set_unsafe(i, undefined as T)
315            }
316
317            sort_default<NullishType>(this.buffer, strArr, 0, sortTo)
318        }
319        catch (e) {
320            if (e instanceof OutOfMemoryError) {
321                this.slow_default_sort()
322            } else {
323                throw e as Error
324            }
325        }
326    }
327
328    private slow_default_sort(): void {
329        let idxNonUndef = 0
330        const cmp: (l: NullishType, r: NullishType) => number = (l: NullishType, r: NullishType): number => {
331            return Array.defaultComparator(l, r)
332        }
333        for (let i = 0; i < this.actualLength; i++) {
334            const vl = this.$_get_unsafe(i)
335            if (!__runtimeIsSameReference(vl, undefined)) {
336                this.$_set_unsafe(idxNonUndef, vl)
337                idxNonUndef++
338            }
339        }
340        let sortTo = idxNonUndef
341        for (let i = idxNonUndef; i < this.actualLength; i++) {
342            this.$_set_unsafe(i, undefined as T)
343        }
344        sort_stable<NullishType>(this.buffer, 0, sortTo, cmp)
345    }
346
347    /**
348     * Reorders elements of `this` using comparator function.
349     *
350     * @param comparator function that defines the sort order.
351     *
352     * @note Mutating method
353     *
354     * NOTE clarify UTF-16 or UTF-8
355     */
356    public sort(comparator?: (a: T, b: T) => number): this {
357        let cmp: (l: NullishType, r: NullishType) => number = (l: NullishType, r: NullishType): number => {
358            return Array.defaultComparator(l, r)
359        }
360        let sortTo = this.actualLength
361        if (!__runtimeIsSameReference(comparator, undefined)) {
362            cmp = (l: NullishType, r: NullishType): number => {
363                return comparator!(l as T, r as T)
364            }
365            sort_stable<NullishType>(this.buffer, 0, sortTo, cmp)
366        } else {
367            this.wrap_default_sort()
368        }
369        return this
370    }
371
372    /**
373     * Removes the first element from an array and returns that removed element.
374     * This method changes the length of the array.
375     *
376     * @returns shifted element, i.e. that was at index zero
377     */
378    public shift(): T | undefined {
379        if(this.actualLength == 0) {
380            return undefined
381        }
382        let obj = this.$_get_unsafe(0)
383        const other = this.slice(1, this.actualLength)
384        this.buffer = other.buffer
385        this.actualLength = other.actualLength
386        return obj
387    }
388
389    /**
390     * Removes the last element from an array and returns that element.
391     * This method changes the length of the array.
392     *
393     * @returns removed element
394     */
395    public pop(): T | undefined {
396        if(this.actualLength == 0) {
397            return undefined
398        }
399        let obj = this.$_get_unsafe(this.actualLength - 1)
400        this.buffer[this.actualLength - 1] = null
401        this.actualLength--
402        return obj
403    }
404
405    // NOTE(kprokopenko): remove when #14756 is fixed and rename below fucntion to push
406    public push(val: T): number {
407        this.ensureUnusedCapacity(1)
408        this.buffer[this.actualLength] = val
409        this.actualLength += 1
410        return this.actualLength
411    }
412
413    /**
414     * Adds the specified elements to the end of an array and returns the new length of the array.
415     *
416     * @returns new length
417     */
418    public pushECMA(...val: T[]): number {
419        this.ensureUnusedCapacity(val.length)
420        for (let i = 0; i < val.length; i++) {
421            this.buffer[this.actualLength + i] = val[i]
422        }
423        this.actualLength += val.length
424        return this.actualLength
425    }
426
427    private ensureUnusedCapacity(cap: int): void {
428        if (this.actualLength + cap > this.buffer.length) {
429            const copy = new NullishType[this.buffer.length * 2 + cap]
430            for (let i = 0; i < this.actualLength; i++) {
431                copy[i] = this.buffer[i]
432            }
433            this.buffer = copy
434        }
435    }
436
437    /**
438     * Changes the contents of an array by removing or replacing existing elements
439     * and/or adding new elements in place.
440     *
441     * @param start index
442     *
443     * @param delete number of items after start index
444     *
445     * @returns an Array with deleted elements
446     */
447    public splice(start: number, delete: Number | undefined, ...items: T[]): Array<T> {
448        return this.splice(start as int, asIntOrDefault(delete, this.actualLength), ...items)
449    }
450
451    /**
452     * Changes the contents of an array by removing or replacing existing elements
453     * and/or adding new elements in place.
454     *
455     * @param start index
456     *
457     * @param delete number of items after start index
458     *
459     * @returns an Array with deleted elements
460     */
461    public splice(start: int, delete: int, ...items: T[]): Array<T> {
462        start = normalizeIndex(start, this.actualLength)
463        if (delete < 0) {
464            delete = 0
465        }
466        if (start > this.actualLength - delete) {
467            delete = this.actualLength - start
468        }
469        // this: [left middle right], we must replace middle with `items`
470
471        this.ensureUnusedCapacity(items.length - delete)
472        const oldLen = this.actualLength
473        this.actualLength = this.actualLength - delete + items.length
474
475        let ret = new Array<T>(delete)
476        let lastSet = start
477        // left part remains unchanged
478        // copy excluded part
479        for (let i = 0; i < delete; i++) {
480            ret.buffer[i] = this.buffer[start + i]
481        }
482        // move right part to the right of the buffer
483        const rightLen = oldLen - start - delete
484        if (items.length > delete) {
485            for (let i = 0; i < rightLen; i++) {
486                this.buffer[this.actualLength - 1 - i] = this.buffer[oldLen - 1 - i]
487            }
488        } else {
489            for (let i = 0; i < rightLen; i++) {
490                this.buffer[start + items.length + i] = this.buffer[start + delete + i]
491            }
492        }
493        // insert middle part
494        for (let i = 0; i < items.length; i++) {
495            this.buffer[start + i] = items[i]
496        }
497        return ret
498    }
499
500    /**
501     * Changes the contents of an array by removing or replacing existing elements
502     * and/or adding new elements in place.
503     *
504     * @param start index
505     *
506     * @returns an Array with deleted elements from start to the last element of the current instance
507     */
508    public splice(start: number): Array<T> {
509        return this.splice(start as int)
510    }
511
512    /**
513     * Changes the contents of an array by removing or replacing existing elements
514     * and/or adding new elements in place.
515     *
516     * @param start index
517     *
518     * @returns an Array with deleted elements from start to the last element of the current instance
519     */
520    public splice(start: int): Array<T> {
521        return this.splice(start, this.actualLength)
522    }
523
524    /**
525     * Checks whether the passed value is an Array.
526     *
527     * @param arr
528     *
529     * @returns true is arr is a non-nullish array, false otherwise
530     */
531    public static isArray(o: NullishType): boolean {
532        if (o instanceof Array) {
533            return true
534        }
535        return (Type.of(o) instanceof ArrayType)
536    }
537
538    /**
539     * Creates a new Array instance from a variable number of arguments,
540     * regardless of number or type of the arguments.
541     *
542     * @param values an initilizer
543     *
544     * @returns a newly created Array
545     */
546    public static of<T>(...values: T[]): Array<T> {
547        const ret = new Array<T>()
548        ret.ensureUnusedCapacity(values.length)
549        for (let i = 0; i < values.length; i++) {
550            ret.push(values[i])
551        }
552        return ret
553    }
554
555    /**
556     * Adds the specified elements to the beginning of an Array
557     * and returns the new length of the Array.
558     *
559     * @param values data to be added
560     *
561     * @returns new length of the Array
562     */
563    public unshift(...values: T[]): number {
564        let buffer = this.buffer
565        if (this.buffer.length <= values.length + this.actualLength) {
566            buffer = new NullishType[this.buffer.length * 2 + values.length]
567        }
568        for (let i = 0; i < this.actualLength; i++) {
569            buffer[this.actualLength + values.length - i - 1] = this.buffer[this.actualLength - 1 - i]
570        }
571        for (let i = 0; i < values.length; i++) {
572            buffer[i] = values[i]
573        }
574        this.buffer = buffer
575        this.actualLength += values.length
576        return this.actualLength
577    }
578
579    /**
580     * Returns an iterator over all indices
581     */
582    public override keys(): IterableIterator<Number> {
583        return new ArrayKeysIterator<T>(this)
584    }
585
586    /**
587     * Returns an iterator over all values
588     */
589    public override $_iterator(): IterableIterator<T> {
590        return this.values()
591    }
592
593    // === methods with uncompatible implementation ===
594    /**
595     * Returns the elements of an array that meet the condition specified in a callback function.
596     *
597     * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
598     *
599     * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
600     */
601    public override filter(predicate: (value: T, index: number) => boolean): Array<T> {
602        const res = new Array<T>()
603        for (let i: int = 0; i < this.actualLength; i++) {
604            const val = this.$_get_unsafe(i)
605            if (predicate(val, i as number)) {
606                res.push(val)
607            }
608        }
609        return res
610    }
611
612    /**
613     * Creates a new Array with all sub-array elements concatenated
614     * into it recursively up to the specified depth.
615     *
616     * @param depth
617     *
618     * @returns a flattened Array with respect to depth
619     */
620    public flat<U>(depth: number): Array<U> {
621        return this.flat<U>(depth as int)
622    }
623
624    /**
625     * Creates a new Array with all sub-array elements concatenated
626     * into it recursively up to the specified depth.
627     *
628     * @param depth
629     *
630     * @returns a flattened Array with respect to depth
631     */
632    public flat<U>(depth: int): Array<U> {
633        let ret = new Array<U>()
634        this.flatImpl<U>(depth, ret)
635        return ret
636    }
637
638    private flatImpl<U>(depth: int, to: Array<U>) {
639        throw new Error("not implemented")
640    }
641
642    /**
643     * Creates a new Array with all sub-array elements concatenated
644     *
645     * @returns a flattened Array
646     */
647    public flat<U>(): Array<U> {
648        return this.flat<U>(1)
649    }
650
651    /**
652     * Applies flat and than map
653     *
654     * fn a function to apply
655     *
656     * @return new Array after map and than flat
657     */
658    // NOTE(ivan-tyulyandin): TBD, flatMap may be not subset, see ReadonlyArray
659    public flatMap<U>(fn: (v: T, k: number, arr: Array<T>) => U): Array<U> {
660        let mapped: Array<U> = this.map<U>(fn)
661        return mapped.flat<U>()
662    }
663
664    /**
665     * Applies flat and than map
666     *
667     * fn a function to apply
668     *
669     * @return new Array after map and than flat
670     */
671     // NOTE(ivan-tyulyandin): TBD, flatMap may be not subset, see ReadonlyArray
672    public flatMap<U>(fn: (v: T, k: number) => U): Array<U> {
673        let mapped: Array<U> = this.map<U>(fn)
674        return mapped.flat<U>()
675    }
676
677    /**
678     * Applies flat and than map
679     *
680     * fn a function to apply
681     *
682     * @return new Array after map and than flat
683     */
684    // NOTE(ivan-tyulyandin): TBD, flatMap may be not subset, see ReadonlyArray
685    public flatMap<U>(fn: (v: T) => U): Array<U> {
686        let mapped: Array<U> = this.map<U>(fn)
687        return mapped.flat<U>()
688    }
689
690    // === methods common among all arrays ===
691
692    /**
693     * Takes an integer value and returns the item at that index,
694     * allowing for positive and negative integers. Negative integers count back
695     * from the last item in the array.
696     *
697     * @param index Zero-based index of the array element to be returned.
698     * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
699     *
700     * @returns The element in the array matching the given index.
701     * Returns undefined if `index` < `-length()` or `index` >= `length()`.
702     */
703    public override at(index: number): T | undefined {
704        return this.at(index as int)
705    }
706
707    /**
708     * Creates a new `Array` from this `Array` instance and given `Array` instance.
709     *
710     * @param other to concatenate into a new array.
711     *
712     * @returns New `Array` instance, constructed from `this` and given `other` instances of `Array` class.
713     */
714    // public override concat(...items: (T | ConcatArray<T>)[]): Array<T> {
715    //     throw new Error("not implemented")
716    // }
717
718    public concat(...items: ConcatArray<T>[]): Array<T> {
719        let totalAdd = this.actualLength;
720        for (let i = 0; i < items.length; i++) {
721            totalAdd += items[i].length as int
722        }
723
724        const buf = new NullishType[totalAdd];
725
726        for (let i = 0; i < this.actualLength; i++) {
727            buf[i] = this.$_get_unsafe(i);
728        }
729
730        let insertTo = this.actualLength;
731        for (let i = 0; i < items.length; i++) {
732            const arr = items[i]
733            const len = arr.length as int
734            for (let j = 0; j < len; j++) {
735                buf[insertTo++] = arr.$_get(j)
736            }
737        }
738
739        return new Array<T>(FROM_BUFFER, buf);
740    }
741
742    /**
743     * Takes an integer value and returns the item at that index,
744     * allowing for positive and negative integers. Negative integers count back
745     * from the last item in the array.
746     *
747     * @param index Zero-based index of the array element to be returned.
748     * Negative index counts back from the end of the array — if `index` < 0, index + `array.length()` is accessed.
749     *
750     * @returns The element in the array matching the given index.
751     * Returns undefined if `index` < `-length()` or `index` >= `length()`.
752     */
753    public at(index: int): T | undefined {
754        let len = this.actualLength;
755        let k: int;
756        if (index >= 0) {
757            k = index;
758        } else {
759            k = len + index;
760        }
761
762        if (k < 0 || k >= len) {
763            return undefined;
764        }
765
766        return this.$_get_unsafe(k);
767    }
768
769    /**
770     * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
771     *
772     * @param target index at which to copy the sequence
773     *
774     * @param start index at which to start copying elements from
775     *
776     * @param end index at which to end copying elements from
777     *
778     * @returns this array after transformation
779     */
780    public copyWithin(target: number, start: number, end?: Number): this {
781        this.copyWithin(target as int, start as int, asIntOrDefault(end, this.actualLength));
782        return this;
783    }
784
785    /**
786     * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
787     *
788     * @param target index at which to copy the sequence
789     *
790     * @param start index at which to start copying elements from
791     *
792     * @param end index at which to end copying elements from
793     *
794     * @returns this array after transformation
795     */
796    public copyWithin(target: int, start: int, end: int): this {
797        target = normalizeIndex(target, this.actualLength)
798        start = normalizeIndex(start, this.actualLength)
799        end = normalizeIndex(end, this.actualLength)
800
801        if (end <= start) {
802            return this;
803        }
804
805        if (target <= start) {
806            while (start < end) {
807                const read = this.$_get_unsafe(start++);
808                this.$_set_unsafe(target++, read);
809            }
810        } else {
811            let len = end - start;
812            if (target + len > this.actualLength) {
813                len = this.actualLength - target
814            }
815            for (let i = 0; i < len; i++) {
816                const read = this.$_get_unsafe(start + len - 1 - i);
817                this.$_set_unsafe(target + len - 1 - i, read);
818            }
819        }
820
821        return this;
822    }
823
824    /**
825     * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
826     *
827     * @param target index at which to copy the sequence
828     *
829     * @param start index at which to start copying elements from
830     *
831     * @returns this array after transformation
832     */
833    public copyWithin(target: int, start: int): this {
834        this.copyWithin(target, start, this.actualLength);
835        return this;
836    }
837
838    /**
839     * Makes a shallow copy of the Array part to another location in the same Array and returns it without modifying its length.
840     *
841     * @param target index at which to copy the sequence
842     *
843     * @returns this array after transformation
844     */
845    public copyWithin(target: int): this {
846        this.copyWithin(target, 0, this.actualLength);
847        return this;
848    }
849
850    /**
851     * Changes all elements in the Array to a static value, from a start index to an end index
852     *
853     * @param value to fill the array with
854     *
855     * @param start index at which to start filling
856     *
857     * @param end index at which to end filling, but not including
858     *
859     * @returns this array after transformation
860     */
861    public fill(value: T, start?: Number, end?: Number): this {
862        this.fill(value, asIntOrDefault(start, 0), asIntOrDefault(end, this.actualLength));
863        return this;
864    }
865
866    /**
867     * Changes all elements in the Array to a static value, from a start index to an end index
868     *
869     * @param value to fill the array with
870     *
871     * @param start index at which to start filling
872     *
873     * @param end index at which to end filling, but not including
874     *
875     * @returns this array after transformation
876     */
877    public fill(value: T, start: int, end: int): this {
878        start = normalizeIndex(start, this.actualLength);
879        end = normalizeIndex(end, this.actualLength)
880
881        for (let i = start; i < end; i++) {
882            this.$_set_unsafe(i, value);
883        }
884
885        return this;
886    }
887
888    /**
889     * Returns the value of the first element in the array where predicate is true, and undefined
890     * otherwise.
891     *
892     * @param predicate find calls predicate once for each element of the array, in ascending
893     * order, until it finds one where predicate returns true. If such an element is found, find
894     * immediately returns that element value. Otherwise, find returns undefined.
895     *
896     * @returns the value of the first element in the array or undefined
897     */
898    public override find(predicate: (value: T, index: number, array: Array<T>) => boolean): T | undefined {
899        const res = this.findIndex(predicate)
900        if (res == -1) {
901            return undefined
902        }
903        return this.$_get_unsafe(res as int);
904    }
905
906    /**
907     * Returns the index of the first element in the array where predicate is true, and -1
908     * otherwise.
909     *
910     * @param predicate find calls predicate once for each element of the array, in ascending
911     * order, until it finds one where predicate returns true. If such an element is found,
912     * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
913     *
914     * @returns found element index or -1 otherwise
915     */
916    public override findIndex(predicate: (value: T, index: number, array: Array<T>) => boolean): number {
917        for (let i = 0; i < this.actualLength; i++) {
918            if (predicate(this.$_get_unsafe(i), i as number, this)) {
919                return i;
920            }
921        }
922        return -1;
923    }
924
925    /**
926     * Iterates the array in reverse order and returns the value of the first element
927     * that satisfies the provided testing function
928     *
929     * @param predicate testing function
930     *
931     * @returns found element or undefined otherwise
932     */
933    public override findLast(predicate: (elem: T, index: number, array: Array<T>) => boolean): T | undefined {
934        for (let i = this.actualLength - 1; i >= 0; i--) {
935            const val = this.$_get_unsafe(i);
936            if (predicate(val, i as number, this)) {
937                return val;
938            }
939        }
940        return undefined;
941    }
942
943    /**
944     * Determines whether all the members of an array satisfy the specified test.
945     *
946     * @param predicate A function that accepts up to three arguments. The every method calls
947     * the predicate function for each element in the array until the predicate returns a value
948     * which is coercible to the Boolean value false, or until the end of the array.
949     *
950     * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
951     */
952    public override every(predicate: (value: T, index: number, array: Array<T>) => boolean): boolean {
953        for (let i = 0; i < this.actualLength; i++) {
954            if (!predicate(this.$_get_unsafe(i), i as number, this)) {
955                return false
956            }
957        }
958        return true;
959    }
960
961    /**
962     * Determines whether the specified callback function returns true for any element of an array.
963     *
964     * @param predicate A function that accepts up to three arguments. The some method calls
965     * the predicate function for each element in the array until the predicate returns a value
966     * which is coercible to the Boolean value true, or until the end of the array.
967     *
968     * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
969     */
970    public override some(predicate: (value: T, index: number, array: Array<T>) => boolean): boolean {
971        for (let i = 0; i < this.actualLength; i++) {
972            if (predicate(this.$_get_unsafe(i), i as number, this)) {
973                return true
974            }
975        }
976        return false
977    }
978
979    /**
980     * Returns the elements of an array that meet the condition specified in a callback function.
981     *
982     * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
983     *
984     * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
985     */
986    public override filter(predicate: (value: T, index: number, array: Array<T>) => boolean): Array<T> {
987        return this.filter((value: T, index: number): boolean => predicate(value, index, this));
988    }
989
990    /**
991     * Iterates the array in reverse order and returns the index of
992     * the first element that satisfies the provided testing function.
993     * If no elements satisfy the testing function, -1 is returned.
994     *
995     * @param predicate testing function
996     *
997     * @returns index of first element satisfying to predicate, -1 if no such element
998     */
999    public override findLastIndex(predicate: (element: T, index: number, array: Array<T>) => boolean): number {
1000        for (let i = this.actualLength - 1; i >= 0; i--) {
1001            if (predicate(this.$_get_unsafe(i), i as number, this)) {
1002                return i
1003            }
1004        }
1005        return -1
1006    }
1007
1008    /**
1009     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1010     *
1011     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1012     *
1013     * @returns a result after applying callbackfn over all elements of the Array
1014     */
1015    public override reduce(callbackfn: (previousValue: T, currentValue: T, index: number, array: Array<T>) => T): T {
1016        if (this.actualLength == 0) {
1017            throw new TypeError("Reduce of empty array with no initial value")
1018        }
1019        let acc: T = this.$_get_unsafe(0);
1020        for (let i = 1; i < this.actualLength; i++) {
1021            acc = callbackfn(acc, this.$_get_unsafe(i), i as number, this)
1022        }
1023        return acc
1024    }
1025
1026    /**
1027     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1028     *
1029     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1030     *
1031     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1032     *
1033     * @returns a result after applying callbackfn over all elements of the Array
1034     */
1035    public override reduce<U = T>(callbackfn: (previousValue: U, currentValue: T, index: number, array: Array<T>) => U, initialValue: U): U {
1036        let acc = initialValue
1037        for (let i = 0; i < this.actualLength; i++) {
1038            acc = callbackfn(acc, this.$_get_unsafe(i), i as number, this)
1039        }
1040        return acc
1041    }
1042
1043    /**
1044     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1045     *
1046     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1047     *
1048     * @returns a result after applying callbackfn over all elements of the Array
1049     */
1050    public override reduceRight(callbackfn: (previousValue: T, currentValue: T, index: number, array: Array<T>) => T): T {
1051        if (this.actualLength == 0) {
1052            throw new TypeError("Reduce of empty array with no initial value")
1053        }
1054        let acc: T = this.$_get_unsafe(this.actualLength - 1);
1055        for (let i = this.actualLength - 2; i >= 0; i--) {
1056            acc = callbackfn(acc, this.$_get_unsafe(i), i as number, this)
1057        }
1058        return acc
1059    }
1060
1061    /**
1062     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1063     *
1064     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1065     *
1066     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1067     *
1068     * @returns a result after applying callbackfn over all elements of the Array
1069     */
1070    public override reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, index: number, array: Array<T>) => U, initialValue: U): U {
1071        let acc = initialValue
1072        for (let i = this.actualLength - 1; i >= 0; i--) {
1073            acc = callbackfn(acc, this.$_get_unsafe(i), i as number, this)
1074        }
1075        return acc
1076    }
1077
1078    /**
1079     * Performs the specified action for each element in an array.
1080     *
1081     * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
1082     */
1083    public override forEach(callbackfn: (value: T, index: number, array: Array<T>) => void): void {
1084        const len0 = this.actualLength;
1085        for (let i = 0; i < len0; i++) {
1086            callbackfn(this.$_get_unsafe(i), i as number, this)
1087        }
1088    }
1089
1090    /**
1091     * Returns the value of the first element in the array where predicate is true, and undefined
1092     * otherwise.
1093     *
1094     * @param predicate find calls predicate once for each element of the array, in ascending
1095     * order, until it finds one where predicate returns true. If such an element is found, find
1096     * immediately returns that element value. Otherwise, find returns undefined.
1097     *
1098     * @returns the value of the first element in the array or undefined
1099     */
1100    public override find(predicate: (value: T, index: number) => boolean): T | undefined {
1101        const res = this.findIndex(predicate)
1102        if (res == -1) {
1103            return undefined
1104        }
1105        return this.$_get_unsafe(res as int);
1106    }
1107
1108    /**
1109     * Returns the index of the first element in the array where predicate is true, and -1
1110     * otherwise.
1111     *
1112     * @param predicate find calls predicate once for each element of the array, in ascending
1113     * order, until it finds one where predicate returns true. If such an element is found,
1114     * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
1115     *
1116     * @returns found element index or -1 otherwise
1117     */
1118    public override findIndex(predicate: (value: T, index: number) => boolean): number {
1119        for (let i = 0; i < this.actualLength; i++) {
1120            if (predicate(this.$_get_unsafe(i), i as number)) {
1121                return i;
1122            }
1123        }
1124        return -1;
1125    }
1126
1127    /**
1128     * Iterates the array in reverse order and returns the value of the first element
1129     * that satisfies the provided testing function
1130     *
1131     * @param predicate testing function
1132     *
1133     * @returns found element or undefined otherwise
1134     */
1135    public override findLast(predicate: (elem: T, index: number) => boolean): T | undefined {
1136        for (let i = this.actualLength - 1; i >= 0; i--) {
1137            const val = this.$_get_unsafe(i);
1138            if (predicate(val, i as number)) {
1139                return val;
1140            }
1141        }
1142        return undefined;
1143    }
1144
1145    /**
1146     * Determines whether all the members of an array satisfy the specified test.
1147     *
1148     * @param predicate A function that accepts up to three arguments. The every method calls
1149     * the predicate function for each element in the array until the predicate returns a value
1150     * which is coercible to the Boolean value false, or until the end of the array.
1151     *
1152     * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
1153     */
1154    public override every(predicate: (value: T, index: number) => boolean): boolean {
1155        for (let i = 0; i < this.actualLength; i++) {
1156            if (!predicate(this.$_get_unsafe(i), i as number)) {
1157                return false
1158            }
1159        }
1160        return true;
1161    }
1162
1163    /**
1164     * Determines whether the specified callback function returns true for any element of an array.
1165     *
1166     * @param predicate A function that accepts up to three arguments. The some method calls
1167     * the predicate function for each element in the array until the predicate returns a value
1168     * which is coercible to the Boolean value true, or until the end of the array.
1169     *
1170     * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
1171     */
1172    public override some(predicate: (value: T, index: number) => boolean): boolean {
1173        for (let i = 0; i < this.actualLength; i++) {
1174            if (predicate(this.$_get_unsafe(i), i as number)) {
1175                return true
1176            }
1177        }
1178        return false
1179    }
1180
1181    /**
1182     * Iterates the array in reverse order and returns the index of
1183     * the first element that satisfies the provided testing function.
1184     * If no elements satisfy the testing function, -1 is returned.
1185     *
1186     * @param predicate testing function
1187     *
1188     * @returns index of first element satisfying to predicate, -1 if no such element
1189     */
1190    public override findLastIndex(predicate: (element: T, index: number) => boolean): number {
1191        for (let i = this.actualLength - 1; i >= 0; i--) {
1192            if (predicate(this.$_get_unsafe(i), i as number)) {
1193                return i
1194            }
1195        }
1196        return -1
1197    }
1198
1199    /**
1200     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1201     *
1202     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1203     *
1204     * @returns a result after applying callbackfn over all elements of the Array
1205     */
1206    public override reduce(callbackfn: (previousValue: T, currentValue: T, index: number) => T): T {
1207        if (this.actualLength == 0) {
1208            throw new TypeError("Reduce of empty array with no initial value")
1209        }
1210        let acc: T = this.$_get_unsafe(0);
1211        for (let i = 1; i < this.actualLength; i++) {
1212            acc = callbackfn(acc, this.$_get_unsafe(i), i as number)
1213        }
1214        return acc
1215    }
1216
1217    /**
1218     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1219     *
1220     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1221     *
1222     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1223     *
1224     * @returns a result after applying callbackfn over all elements of the Array
1225     */
1226    public override reduce<U = T>(callbackfn: (previousValue: U, currentValue: T, index: number) => U, initialValue: U): U {
1227        let acc = initialValue
1228        for (let i = 0; i < this.actualLength; i++) {
1229            acc = callbackfn(acc, this.$_get_unsafe(i), i as number)
1230        }
1231        return acc
1232    }
1233
1234    /**
1235     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1236     *
1237     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1238     *
1239     * @returns a result after applying callbackfn over all elements of the Array
1240     */
1241    public override reduceRight(callbackfn: (previousValue: T, currentValue: T, index: number) => T): T {
1242        if (this.actualLength == 0) {
1243            throw new TypeError("Reduce of empty array with no initial value")
1244        }
1245        let acc: T = this.$_get_unsafe(this.actualLength - 1);
1246        for (let i = this.actualLength - 2; i >= 0; i--) {
1247            acc = callbackfn(acc, this.$_get_unsafe(i), i as number)
1248        }
1249        return acc
1250    }
1251
1252    /**
1253     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1254     *
1255     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1256     *
1257     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1258     *
1259     * @returns a result after applying callbackfn over all elements of the Array
1260     */
1261    public override reduceRight<U>(callbackfn: (previousValue: U, currentValue: T, index: number) => U, initialValue: U): U {
1262        let acc = initialValue
1263        for (let i = this.actualLength - 1; i >= 0; i--) {
1264            acc = callbackfn(acc, this.$_get_unsafe(i), i as number)
1265        }
1266        return acc
1267    }
1268
1269    /**
1270     * Performs the specified action for each element in an array.
1271     *
1272     * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
1273     */
1274    public override forEach(callbackfn: (value: T, index: number) => void): void {
1275        const len0 = this.actualLength;
1276        for (let i = 0; i < len0; i++) {
1277            callbackfn(this.$_get_unsafe(i), i as number)
1278        }
1279    }
1280
1281    /**
1282     * Returns the value of the first element in the array where predicate is true, and undefined
1283     * otherwise.
1284     *
1285     * @param predicate find calls predicate once for each element of the array, in ascending
1286     * order, until it finds one where predicate returns true. If such an element is found, find
1287     * immediately returns that element value. Otherwise, find returns undefined.
1288     *
1289     * @returns the value of the first element in the array or undefined
1290     */
1291    public override find(predicate: (value: T) => boolean): T | undefined {
1292        const res = this.findIndex(predicate)
1293        if (res == -1) {
1294            return undefined
1295        }
1296        return this.$_get_unsafe(res as int);
1297    }
1298
1299    /**
1300     * Returns the index of the first element in the array where predicate is true, and -1
1301     * otherwise.
1302     *
1303     * @param predicate find calls predicate once for each element of the array, in ascending
1304     * order, until it finds one where predicate returns true. If such an element is found,
1305     * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
1306     *
1307     * @returns found element index or -1 otherwise
1308     */
1309    public override findIndex(predicate: (value: T) => boolean): number {
1310        for (let i = 0; i < this.actualLength; i++) {
1311            if (predicate(this.$_get_unsafe(i))) {
1312                return i;
1313            }
1314        }
1315        return -1;
1316    }
1317
1318    /**
1319     * Iterates the array in reverse order and returns the value of the first element
1320     * that satisfies the provided testing function
1321     *
1322     * @param predicate testing function
1323     *
1324     * @returns found element or undefined otherwise
1325     */
1326    public override findLast(predicate: (elem: T) => boolean): T | undefined {
1327        for (let i = this.actualLength - 1; i >= 0; i--) {
1328            const val = this.$_get_unsafe(i);
1329            if (predicate(val)) {
1330                return val;
1331            }
1332        }
1333        return undefined;
1334    }
1335
1336    /**
1337     * Determines whether all the members of an array satisfy the specified test.
1338     *
1339     * @param predicate A function that accepts up to three arguments. The every method calls
1340     * the predicate function for each element in the array until the predicate returns a value
1341     * which is coercible to the Boolean value false, or until the end of the array.
1342     *
1343     * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
1344     */
1345    public override every(predicate: (value: T) => boolean): boolean {
1346        for (let i = 0; i < this.actualLength; i++) {
1347            if (!predicate(this.$_get_unsafe(i))) {
1348                return false
1349            }
1350        }
1351        return true;
1352    }
1353
1354    /**
1355     * Determines whether the specified callback function returns true for any element of an array.
1356     *
1357     * @param predicate A function that accepts up to three arguments. The some method calls
1358     * the predicate function for each element in the array until the predicate returns a value
1359     * which is coercible to the Boolean value true, or until the end of the array.
1360     *
1361     * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
1362     */
1363    public override some(predicate: (value: T) => boolean): boolean {
1364        for (let i = 0; i < this.actualLength; i++) {
1365            if (predicate(this.$_get_unsafe(i))) {
1366                return true
1367            }
1368        }
1369        return false
1370    }
1371
1372    /**
1373     * Returns the elements of an array that meet the condition specified in a callback function.
1374     *
1375     * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
1376     *
1377     * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
1378     */
1379    public override filter(predicate: (value: T) => boolean): Array<T> {
1380        return this.filter((value: T, index: number): boolean => predicate(value));
1381    }
1382
1383    /**
1384     * Iterates the array in reverse order and returns the index of
1385     * the first element that satisfies the provided testing function.
1386     * If no elements satisfy the testing function, -1 is returned.
1387     *
1388     * @param predicate testing function
1389     *
1390     * @returns index of first element satisfying to predicate, -1 if no such element
1391     */
1392    public override findLastIndex(predicate: (element: T) => boolean): number {
1393        for (let i = this.actualLength - 1; i >= 0; i--) {
1394            if (predicate(this.$_get_unsafe(i))) {
1395                return i
1396            }
1397        }
1398        return -1
1399    }
1400
1401    /**
1402     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1403     *
1404     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1405     *
1406     * @returns a result after applying callbackfn over all elements of the Array
1407     */
1408    public override reduce(callbackfn: (previousValue: T, currentValue: T) => T): T {
1409        if (this.actualLength == 0) {
1410            throw new TypeError("Reduce of empty array with no initial value")
1411        }
1412        let acc: T = this.$_get_unsafe(0);
1413        for (let i = 1; i < this.actualLength; i++) {
1414            acc = callbackfn(acc, this.$_get_unsafe(i))
1415        }
1416        return acc
1417    }
1418
1419    /**
1420     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1421     *
1422     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
1423     *
1424     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1425     *
1426     * @returns a result after applying callbackfn over all elements of the Array
1427     */
1428    public override reduce<U = T>(callbackfn: (previousValue: U, currentValue: T) => U, initialValue: U): U {
1429        let acc = initialValue
1430        for (let i = 0; i < this.actualLength; i++) {
1431            acc = callbackfn(acc, this.$_get_unsafe(i))
1432        }
1433        return acc
1434    }
1435
1436    /**
1437     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1438     *
1439     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1440     *
1441     * @returns a result after applying callbackfn over all elements of the Array
1442     */
1443    public override reduceRight(callbackfn: (previousValue: T, currentValue: T) => T): T {
1444        if (this.actualLength == 0) {
1445            throw new TypeError("Reduce of empty array with no initial value")
1446        }
1447        let acc: T = this.$_get_unsafe(this.actualLength - 1);
1448        for (let i = this.actualLength - 2; i >= 0; i--) {
1449            acc = callbackfn(acc, this.$_get_unsafe(i))
1450        }
1451        return acc
1452    }
1453
1454    /**
1455     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
1456     *
1457     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
1458     *
1459     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
1460     *
1461     * @returns a result after applying callbackfn over all elements of the Array
1462     */
1463    public override reduceRight<U>(callbackfn: (previousValue: U, currentValue: T) => U, initialValue: U): U {
1464        let acc = initialValue
1465        for (let i = this.actualLength - 1; i >= 0; i--) {
1466            acc = callbackfn(acc, this.$_get_unsafe(i))
1467        }
1468        return acc
1469    }
1470
1471    /**
1472     * Performs the specified action for each element in an array.
1473     *
1474     * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
1475     */
1476    public override forEach(callbackfn: (value: T) => void): void {
1477        const len0 = this.actualLength;
1478        for (let i = 0; i < len0; i++) {
1479            callbackfn(this.$_get_unsafe(i))
1480        }
1481    }
1482
1483    /**
1484     * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
1485     * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
1486     *
1487     * @param start zero-based index at which to start extraction
1488     *
1489     * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
1490     *
1491     * @returns `Array` instance, constructed from extracted elements of `this` instance.
1492     */
1493    public override slice(start?: Number, end?: Number): Array<T> {
1494        const len: int = this.actualLength;
1495        return this.slice(asIntOrDefault(start, 0), asIntOrDefault(end, len))
1496    }
1497
1498    /**
1499     * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
1500     * selected from `start` to `end` (`end` not included) where `start` and `end` represent the index of items in that array.
1501     *
1502     * @param start zero-based index at which to start extraction
1503     *
1504     * @param end zero-based index at which to end extraction. `slice()` extracts up to but not including end.
1505     *
1506     * @returns `Array` instance, constructed from extracted elements of `this` instance.
1507     */
1508    public slice(start: int, end: int): Array<T> {
1509        const len: int = this.actualLength;
1510        const relStart = normalizeIndex(start, len)
1511        const relEnd = normalizeIndex(end, len)
1512
1513        let count = relEnd - relStart;
1514        if (count < 0) {
1515            count = 0;
1516        }
1517        let res = new NullishType[count]
1518        for (let i = 0; i < count; i++) {
1519            res[i] = this.$_get_unsafe(relStart + i);
1520        }
1521
1522        return new Array<T>(FROM_BUFFER, res)
1523    }
1524
1525    /**
1526     * Creates a new `Array` object and populates it with elements of `this` instance of `Array` class
1527     * selected from `start` to `Int.MAX_VALUE`, which means 'to the end of an array'.
1528     *
1529     * @param start zero-based index at which to start extraction
1530     *
1531     * @returns `Array` instance, constructed from extracted elements of `this` instance.
1532     */
1533    public slice(start: int): Array<T> {
1534        return this.slice(start, Int.MAX_VALUE as int);
1535    }
1536
1537    /**
1538     * Returns the last index at which a given element can be found in the array,
1539     * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
1540     *
1541     * @param searchElement element to locate in the array.
1542     *
1543     * @param fromIndex zero-based index at which to start searching backwards.
1544     * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
1545     * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
1546     * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
1547     * If `fromIndex` is undefined then `fromIndex = 0`.
1548     * If `fromIndex` is ommited then `fromIndex = length()-1`.
1549     *
1550     * @returns The last index of the element in the array; -1 if not found.
1551     */
1552     public lastIndexOf(searchElement: T, fromIndex: int): int {
1553        if (this.actualLength == 0) {
1554            return -1;
1555        }
1556        let n = fromIndex;
1557        let k: int;
1558        if (n >= 0) {
1559            k = min(this.actualLength - 1, n);
1560        } else {
1561            k = this.actualLength + n;
1562        }
1563
1564        while (k >= 0) {
1565            if (__runtimeEquals(this.$_get_unsafe(k), searchElement)) {
1566                return k;
1567            }
1568            k--;
1569        }
1570        return -1;
1571    }
1572
1573    /**
1574     * Returns the last index at which a given element can be found in the array,
1575     * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
1576     *
1577     * @param searchElement element to locate in the array.
1578     *
1579     * @param fromIndex zero-based index at which to start searching backwards.
1580     * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
1581     * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
1582     * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
1583     * If `fromIndex` is undefined then `fromIndex = 0`.
1584     * If `fromIndex` is ommited then `fromIndex = length()-1`.
1585     *
1586     * @returns The last index of the element in the array; -1 if not found.
1587     */
1588    public lastIndexOf(searchElement: T, fromIndex: number|undefined): number {
1589        return this.lastIndexOf(searchElement, asIntOrDefault(fromIndex, 0));
1590    }
1591
1592    /**
1593     * Returns the last index at which a given element can be found in the array,
1594     * or -1 if it is not present. The array is searched backwards, starting at fromIndex.
1595     *
1596     * @param searchElement element to locate in the array.
1597     *
1598     * @param fromIndex zero-based index at which to start searching backwards.
1599     * Negative index counts back from the end of the array — if `fromIndex` < 0, `fromIndex` + `length()` is used.
1600     * If `fromIndex` < `-length()`, the array is not searched and -1 is returned.
1601     * If `fromIndex` >= `length()` then `array.length - 1` is used, causing the entire array to be searched.
1602     * If `fromIndex` is undefined then `fromIndex = 0`.
1603     * If `fromIndex` is ommited then `fromIndex = length()-1`.
1604     *
1605     * @returns The last index of the element in the array; -1 if not found.
1606     */
1607    public lastIndexOf(searchElement: T): number {
1608        return this.lastIndexOf(searchElement, this.actualLength - 1);
1609    }
1610
1611    /**
1612     * Creates and returns a new string by concatenating all of the elements in an `Array`,
1613     * separated by a specified separator string.
1614     * If the array has only one item, then that item will be returned without using the separator.
1615     *
1616     * @param sep specifies a separator
1617     *
1618     * @returns A string with all array elements joined. If `length()` is 0, the empty string is returned.
1619     */
1620    public override join(sep?: String): string {
1621        const sepReal = __runtimeIsSameReference(sep, undefined) ? "," : sep!
1622        let sb = new StringBuilder()
1623        for (let i: int = 0; i < this.actualLength; i++) {
1624            const tmp = this.$_get_unsafe(i)
1625            // NOTE(aleksander-sotov) We can't move if from loop due to 18709
1626            if (i != 0) {
1627                sb.append(sepReal);
1628            }
1629            // NOTE(aleksander-sotov) We can't call String constructor here due to internal issue 18583
1630            if (!__runtimeIsSameReference(tmp, undefined)) {
1631                sb.append(new String(tmp))
1632            } else {
1633                sb.append("undefined")
1634            }
1635        }
1636
1637        return sb.toString();
1638    }
1639
1640    /**
1641     * Returns a string representing the specified array and its elements.
1642     *
1643     * @returns string representation
1644     */
1645    public override toString(): string {
1646        return this.join(",");
1647    }
1648
1649    /**
1650     * Returns a locale string representing the specified array and its elements.
1651     *
1652     * @param locales
1653     *
1654     * @param options
1655     *
1656     * @returns string representation
1657     */
1658    public toLocaleString(locales: Object, options: Object): string {
1659        throw new Error("Array.toLocaleString: not implemented")
1660    }
1661
1662    /**
1663     * Returns a locale string representing the specified array and its elements.
1664     *
1665     * @param options
1666     *
1667     * @returns string representation
1668     */
1669    public toLocaleString(locales: Object): string {
1670        return this.toLocaleString(new Object(), new Object())
1671    }
1672
1673    /**
1674     * Returns a locale string representing the specified array and its elements.
1675     *
1676     * @returns string representation
1677     */
1678    public override toLocaleString(): string {
1679        const sb = new StringBuilder()
1680        const len = this.actualLength;
1681        for (let i = 0; i < len; i++) {
1682            if (i != 0) {
1683                sb.append(",")
1684            }
1685            let x = this.$_get_unsafe(i) as NullishType;
1686            if (!__runtimeIsSameReference(null, x) && !__runtimeIsSameReference(undefined, x)) {
1687                sb.append(x!.toLocaleString())
1688            }
1689        }
1690        return sb.toString()
1691    }
1692
1693    /**
1694     * Copying version of the splice() method.
1695     *
1696     * @param start index
1697     *
1698     * @param delete number of items after start index
1699     *
1700     * @returns a new Array with some elements removed and/or replaced at a given index.
1701     */
1702    public toSpliced(start?: Number, delete?: Number): Array<T> {
1703        const len = this.actualLength;
1704        return this.toSpliced(asIntOrDefault(start, len), asIntOrDefault(delete, len))
1705    }
1706
1707    /**
1708     * Copying version of the splice() method.
1709     *
1710     * @param start index
1711     *
1712     * @param delete number of items after start index
1713     *
1714     * @returns a new Array with some elements removed and/or replaced at a given index.
1715     */
1716    public toSpliced(start: number, delete: number, ...items: T[]): Array<T> {
1717        const len = this.actualLength;
1718        return this.toSpliced(start as int, delete as int, ...items)
1719    }
1720
1721    /**
1722     * Copying version of the splice() method.
1723     *
1724     * @param start index
1725     *
1726     * @param delete number of items after start index
1727     *
1728     * @returns a new Array with some elements removed and/or replaced at a given index.
1729     */
1730    public toSpliced(start: int, delete: int, ...items: T[]): Array<T> {
1731        const len = this.actualLength;
1732        start = normalizeIndex(start, len);
1733        if (delete < 0) {
1734            delete = 0;
1735        } else if (delete > len) {
1736            delete = len;
1737        }
1738        if (start > len - delete) {
1739            delete = len - start
1740        }
1741        const res = new NullishType[len - delete + items.length];
1742        for (let i = 0; i < start; i++) {
1743            res[i] = this.$_get_unsafe(i)
1744        }
1745        for (let i = 0; i < items.length; i++) {
1746            res[start + i] = items[i]
1747        }
1748        for (let i = start + delete; i < len; i++) {
1749            res[i - delete + items.length] = this.$_get_unsafe(i)
1750        }
1751        return new Array<T>(FROM_BUFFER, res);
1752    }
1753
1754    /**
1755     * Copying version of the splice() method.
1756     *
1757     * @param start index
1758     *
1759     * @returns a new Array with some elements removed and/or replaced at a given index.
1760     */
1761    public toSpliced(start: int): Array<T> {
1762        return this.toSpliced(start, this.actualLength)
1763    }
1764
1765    /**
1766     * Checks whether an Array includes a certain value among its entries,
1767     * returning true or false as appropriate.
1768     *
1769     * @param val value to search
1770     *
1771     * @param fromIndex start index
1772     *
1773     * @returns true if val is in Array
1774     */
1775    public override includes(val: T, fromIndex?: Number): boolean {
1776        const len = this.actualLength;
1777        const fi = normalizeIndex(asIntOrDefault(fromIndex, 0), len);
1778        for (let i = fi; i < len; i++) {
1779            if (__runtimeSameValueZero(val, this.$_get_unsafe(i))) {
1780                return true;
1781            }
1782        }
1783        return false;
1784    }
1785
1786    /**
1787     * Returns the first index at which a given element
1788     * can be found in the array, or -1 if it is not present.
1789     *
1790     * @param val value to search
1791     *
1792     * @param fromIndex index to search from
1793     *
1794     * @returns index of val, -1 otherwise
1795     */
1796    public indexOf(val: T, fromIndex: int): int {
1797        fromIndex = normalizeIndex(fromIndex, this.actualLength)
1798        for (let i = fromIndex; i < this.actualLength; i++) {
1799            if (__runtimeEquals(val, this.$_get_unsafe(i))) {
1800                return i
1801            }
1802        }
1803        return -1
1804    }
1805
1806    /**
1807     * Returns the first index at which a given element
1808     * can be found in the array, or -1 if it is not present.
1809     *
1810     * @param val value to search
1811     *
1812     * @param fromIndex index to search from
1813     *
1814     * @returns index of val, -1 otherwise
1815     */
1816    public override indexOf(val: T, fromIndex?: Number): number {
1817        return this.indexOf(val, asIntOrDefault(fromIndex, 0))
1818    }
1819
1820    /**
1821     * Copying version of the sort() method.
1822     * It returns a new array with the elements sorted in ascending order.
1823     *
1824     * @returns sorted copy of hte current instance using default comparator
1825     */
1826    public toSorted(): Array<T> {
1827        let arr = new Array<T>(FROM_BUFFER, this.copyArray());
1828        arr.sort()
1829        return arr
1830    }
1831
1832    /**
1833     * Copying version of the sort() method.
1834     * It returns a new array with the elements sorted in ascending order.
1835     *
1836     * @param comparator function to compare to elements of the Array
1837     *
1838     * @returns sorted copy of the current instance comparator
1839     */
1840    public toSorted(comparator: (a: T, b: T) => number): Array<T> {
1841        let arr = new Array<T>(FROM_BUFFER, this.copyArray());
1842        arr.sort(comparator)
1843        return arr
1844    }
1845
1846    /**
1847     * Modifies `this` instance of `Array` class and populates
1848     * it with same elements ordered towards the direction opposite to that previously stated.
1849     *
1850     * @note Mutating method
1851     */
1852    public reverse(): this {
1853        for (let i = 0; i < this.actualLength / 2; i++) {
1854            const tmp = this.$_get_unsafe(i);
1855            const idx_r = this.actualLength - 1 - i;
1856            const val_r = this.$_get_unsafe(idx_r);
1857            this.$_set_unsafe(i, val_r);
1858            this.$_set_unsafe(idx_r, tmp);
1859        }
1860        return this;
1861    }
1862
1863    /**
1864     * Copying version of the reverse() method.
1865     * It returns a new array with the elements in reversed order.
1866     *
1867     * @returns reversed copy of the current Array
1868     */
1869    public toReversed(): Array<T> {
1870        let arr = new NullishType[this.actualLength]
1871        for (let i = 0; i < this.actualLength; i++) {
1872            arr[this.actualLength - 1 - i] = this.$_get_unsafe(i)
1873        }
1874        return new Array<T>(FROM_BUFFER, arr)
1875    }
1876
1877    /**
1878     * Copying version of using the bracket notation to change the value of a given index.
1879     * It returns a new Array with the element at the given index replaced with the given value.
1880     *
1881     * @param index to replace
1882     *
1883     * @param value new value
1884     *
1885     * @returns a new Array with the element at the given index replaced with the given value
1886     */
1887    public with(index: number, value: T): Array<T> {
1888        return this.with(index as int, value)
1889    }
1890
1891    /**
1892     * Copying version of using the bracket notation to change the value of a given index.
1893     * It returns a new Array with the element at the given index replaced with the given value.
1894     *
1895     * @param index to replace
1896     *
1897     * @param value new value
1898     *
1899     * @returns a new Array with the element at the given index replaced with the given value
1900     */
1901    public with(index: int, value: T): Array<T> {
1902        if (index < 0) {
1903            index += this.actualLength;
1904        }
1905        if (index >= this.actualLength) {
1906            throw new RangeError("Invalid index")
1907        }
1908        let arr = new Array<T>(FROM_BUFFER, this.copyArray());
1909        arr.$_set_unsafe(index, value);
1910        return arr
1911    }
1912
1913    /**
1914     * Returns an iterator over all values
1915     */
1916    public override values(): IterableIterator<T> {
1917        return new ArrayValuesIterator_T<T>(this);
1918    }
1919
1920    /**
1921     * Returns an iterable of key, value pairs for every entry in the array
1922     */
1923    public override entries(): IterableIterator<[number, T]> {
1924        return new ArrayEntriesIterator_T<T>(this);
1925    }
1926
1927    /**
1928     * Determines whether all the members of an array satisfy the specified test.
1929     *
1930     * @param predicate A function that accepts up to three arguments. The every method calls
1931     * the predicate function for each element in the array until the predicate returns a value
1932     * which is coercible to the Boolean value false, or until the end of the array.
1933     *
1934     * @returns `true` if `predicate` returns a `true` value for every array element. Otherwise, `false`.
1935     */
1936    public override every(predicate: () => boolean): boolean {
1937        for (let i = 0; i < this.actualLength; i++) {
1938            if (!predicate()) {
1939                return false
1940            }
1941        }
1942        return true
1943    }
1944
1945    /**
1946     * Returns the elements of an array that meet the condition specified in a callback function.
1947     *
1948     * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
1949     *
1950     * @returns New `Array` instance constructed from `this` with elements filtered using test function `predicate`.
1951     */
1952    public override filter(predicate: () => boolean): Array<T> {
1953        return this.filter((value: T, index: number): boolean => predicate());
1954    }
1955
1956    /**
1957     * Returns the value of the first element in the array where predicate is true, and undefined
1958     * otherwise.
1959     *
1960     * @param predicate find calls predicate once for each element of the array, in ascending
1961     * order, until it finds one where predicate returns true. If such an element is found, find
1962     * immediately returns that element value. Otherwise, find returns undefined.
1963     *
1964     * @returns the value of the first element in the array or undefined
1965     */
1966    public override find(predicate: () => boolean): T | undefined {
1967        const res = this.findIndex(predicate)
1968        if (res == -1) {
1969            return undefined
1970        }
1971        return this.$_get_unsafe(res as int);
1972    }
1973
1974    /**
1975     * Returns the index of the first element in the array where predicate is true, and -1
1976     * otherwise.
1977     *
1978     * @param predicate find calls predicate once for each element of the array, in ascending
1979     * order, until it finds one where predicate returns true. If such an element is found,
1980     * findIndex immediately returns that element index. Otherwise, findIndex returns -1.
1981     *
1982     * @returns found element index or -1 otherwise
1983     */
1984    public override findIndex(predicate: () => boolean): number {
1985        for (let i = 0; i < this.actualLength; i++) {
1986            if (predicate()) {
1987                return i;
1988            }
1989        }
1990        return -1;
1991    }
1992
1993    /**
1994     * Performs the specified action for each element in an array.
1995     *
1996     * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
1997     */
1998    public override forEach(callbackfn: () => void): void {
1999        const len0 = this.actualLength;
2000        for (let i = 0; i < len0; i++) {
2001            callbackfn()
2002        }
2003    }
2004
2005    /**
2006     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2007     *
2008     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2009     *
2010     * @returns a result after applying callbackfn over all elements of the Array
2011     */
2012    public override reduce(callbackfn: (previousValue: T) => T): T {
2013        if (this.actualLength == 0) {
2014            throw new TypeError("Reduce of empty array with no initial value")
2015        }
2016        let acc: T = this.$_get_unsafe(0);
2017        for (let i = 1; i < this.actualLength; i++) {
2018            acc = callbackfn(acc)
2019        }
2020        return acc
2021    }
2022
2023    /**
2024     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2025     *
2026     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2027     *
2028     * @returns a result after applying callbackfn over all elements of the Array
2029     */
2030    public override reduce(callbackfn: () => T): T {
2031        if (this.actualLength == 0) {
2032            throw new TypeError("Reduce of empty array with no initial value")
2033        }
2034        let acc: T = this.$_get_unsafe(0);
2035        for (let i = 1; i < this.actualLength; i++) {
2036            acc = callbackfn()
2037        }
2038        return acc
2039    }
2040
2041    /**
2042     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2043     *
2044     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2045     *
2046     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2047     *
2048     * @returns a result after applying callbackfn over all elements of the Array
2049     */
2050    public override reduce<U = T>(callbackfn: (previousValue: U) => U, initialValue: U): U {
2051        let acc = initialValue
2052        for (let i = 0; i < this.actualLength; i++) {
2053            acc = callbackfn(acc)
2054        }
2055        return acc
2056    }
2057
2058    /**
2059     * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2060     *
2061     * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
2062     *
2063     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2064     *
2065     * @returns a result after applying callbackfn over all elements of the Array
2066     */
2067    public override reduce<U = T>(callbackfn: () => U, initialValue: U): U {
2068        let acc = initialValue
2069        for (let i = 0; i < this.actualLength; i++) {
2070            acc = callbackfn()
2071        }
2072        return acc
2073    }
2074
2075    /**
2076     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2077     *
2078     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2079     *
2080     * @returns a result after applying callbackfn over all elements of the Array
2081     */
2082    public override reduceRight(callbackfn: (previousValue: T) => T): T {
2083        if (this.actualLength == 0) {
2084            throw new TypeError("Reduce of empty array with no initial value")
2085        }
2086        let acc: T = this.$_get_unsafe(this.actualLength - 1);
2087        for (let i = this.actualLength - 2; i >= 0; i--) {
2088            acc = callbackfn(acc)
2089        }
2090        return acc
2091    }
2092
2093    /**
2094     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2095     *
2096     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2097     *
2098     * @returns a result after applying callbackfn over all elements of the Array
2099     */
2100    public override reduceRight(callbackfn: () => T): T {
2101        if (this.actualLength == 0) {
2102            throw new TypeError("Reduce of empty array with no initial value")
2103        }
2104        let acc: T = this.$_get_unsafe(this.actualLength - 1);
2105        for (let i = this.actualLength - 2; i >= 0; i--) {
2106            acc = callbackfn()
2107        }
2108        return acc
2109    }
2110
2111    /**
2112     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2113     *
2114     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2115     *
2116     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2117     *
2118     * @returns a result after applying callbackfn over all elements of the Array
2119     */
2120    public override reduceRight<U>(callbackfn: (previousValue: U) => U, initialValue: U): U {
2121        let acc = initialValue
2122        for (let i = this.actualLength - 1; i >= 0; i--) {
2123            acc = callbackfn(acc)
2124        }
2125        return acc
2126    }
2127
2128    /**
2129     * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
2130     *
2131     * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
2132     *
2133     * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
2134     *
2135     * @returns a result after applying callbackfn over all elements of the Array
2136     */
2137    public override reduceRight<U>(callbackfn: () => U, initialValue: U): U {
2138        let acc = initialValue
2139        for (let i = this.actualLength - 1; i >= 0; i--) {
2140            acc = callbackfn()
2141        }
2142        return acc
2143    }
2144
2145    /**
2146     * Determines whether the specified callback function returns true for any element of an array.
2147     *
2148     * @param predicate A function that accepts up to three arguments. The some method calls
2149     * the predicate function for each element in the array until the predicate returns a value
2150     * which is coercible to the Boolean value true, or until the end of the array.
2151     *
2152     * @returns `true` if `predicate` returns a `true` value for at least one array element. Otherwise, `false`.
2153     */
2154    public override some(predicate: () => boolean): boolean {
2155        for (let i = 0; i < this.actualLength; i++) {
2156            if (predicate()) {
2157                return true
2158            }
2159        }
2160        return false
2161    }
2162
2163    /**
2164     * Iterates the array in reverse order and returns the value of the first element
2165     * that satisfies the provided testing function
2166     *
2167     * @param predicate testing function
2168     *
2169     * @returns found element or undefined otherwise
2170     */
2171    public override findLast(predicate: () => boolean): T | undefined {
2172        for (let i = this.actualLength - 1; i >= 0; i--) {
2173            const val = this.$_get_unsafe(i);
2174            if (predicate()) {
2175                return val;
2176            }
2177        }
2178        return undefined;
2179    }
2180
2181    /**
2182     * Iterates the array in reverse order and returns the index of
2183     * the first element that satisfies the provided testing function.
2184     * If no elements satisfy the testing function, -1 is returned.
2185     *
2186     * @param predicate testing function
2187     *
2188     * @returns index of first element satisfying to predicate, -1 if no such element
2189     */
2190    public override findLastIndex(predicate: () => boolean): number {
2191        for (let i = this.actualLength - 1; i >= 0; i--) {
2192            if (predicate()) {
2193                return i
2194            }
2195        }
2196        return -1
2197    }
2198
2199    /**
2200     * Calls a defined callback function on each element of an array, and returns an array that contains the results.
2201     *
2202     * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
2203     *
2204     * @returns `Array` instance, constructed from `this` and given function.
2205     */
2206    public override map<U>(callbackfn: (value: T, index: number, array: Array<T>) => U): Array<U> {
2207        const len = this.actualLength;
2208        let res = new NullishType[len];
2209        for (let i = 0; i < len; i++) {
2210            res[i] = callbackfn(this.$_get_unsafe(i), i as number, this);
2211        }
2212        return new Array<U>(FROM_BUFFER, res);
2213    }
2214
2215    /**
2216     * Calls a defined callback function on each element of an array, and returns an array that contains the results.
2217     *
2218     * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
2219     *
2220     * @returns `Array` instance, constructed from `this` and given function.
2221     */
2222    public override map<U>(callbackfn: (value: T, index: number) => U): Array<U> {
2223        const len = this.actualLength;
2224        let res = new NullishType[len];
2225        for (let i = 0; i < len; i++) {
2226            res[i] = callbackfn(this.$_get_unsafe(i), i as number);
2227        }
2228        return new Array<U>(FROM_BUFFER, res);
2229    }
2230
2231    /**
2232     * Calls a defined callback function on each element of an array, and returns an array that contains the results.
2233     *
2234     * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
2235     *
2236     * @returns `Array` instance, constructed from `this` and given function.
2237     */
2238    public override map<U>(callbackfn: (value: T) => U): Array<U> {
2239        const len = this.actualLength;
2240        let res = new NullishType[len];
2241        for (let i = 0; i < len; i++) {
2242            res[i] = callbackfn(this.$_get_unsafe(i));
2243        }
2244        return new Array<U>(FROM_BUFFER, res);
2245    }
2246
2247    /**
2248     * Calls a defined callback function on each element of an array, and returns an array that contains the results.
2249     *
2250     * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
2251     *
2252     * @returns `Array` instance, constructed from `this` and given function.
2253     */
2254    public map<U>(callbackfn: () => U): Array<U> {
2255        const len = this.actualLength;
2256        let res = new NullishType[len];
2257        for (let i = 0; i < len; i++) {
2258            res[i] = callbackfn();
2259        }
2260        return new Array<U>(FROM_BUFFER, res);
2261    }
2262
2263}
2264
2265class ArrayValuesIterator_T<T> implements IterableIterator<T> {
2266    private parent: Array<T>
2267    private idx: int = 0
2268
2269    constructor(parent: Array<T>) {
2270        this.parent = parent
2271    }
2272
2273    override next(): IteratorResult<T> {
2274        if (this.idx >= this.parent.actualLength) {
2275            return new IteratorResult<T>()
2276        }
2277        return new IteratorResult<T>(this.parent.$_get_unsafe(this.idx++))
2278    }
2279
2280    override $_iterator(): IterableIterator<T> {
2281        return this;
2282    }
2283}
2284
2285class ArrayEntriesIterator_T<T> implements IterableIterator<[number, T]> {
2286    private parent: Array<T>
2287    private idx: int = 0
2288
2289    constructor(parent: Array<T>) {
2290        this.parent = parent
2291    }
2292
2293    override next(): IteratorResult<[number, T]> {
2294        if (this.idx >= this.parent.actualLength) {
2295            return new IteratorResult<[number, T]>()
2296        }
2297        const i = this.idx++;
2298        const vl: [number, T] = [i as number, this.parent.$_get_unsafe(i)]
2299        return new IteratorResult<[number, T]>(vl);
2300    }
2301
2302    override $_iterator(): IterableIterator<[number, T]> {
2303        return this;
2304    }
2305}
2306