fix: some array function fixes

This commit is contained in:
2025-01-06 13:24:09 +02:00
parent 3d5be60fc7
commit 7883af7fff
2 changed files with 6 additions and 206 deletions

View File

@@ -0,0 +1,330 @@
import { Error } from "../values/errors.ts";
import { func, object, string } from "../primordials.ts";
import { String } from "../values/string.ts";
import { limitI, symbols, wrapI } from "../utils.ts";
export const Array = (() => {
class Array {
public forEach(this: any[], cb: (val: any, i: number, self: this) => void, self?: any) {
for (let i = 0; i < this.length; i++) {
if (i in this) func.invoke(cb, self, [this[i], i, this]);
}
}
public join(this: any[], delim = ",") {
delim = String(delim);
const parts = [];
if (delim) {
for (let i = 0; i < this.length; i++) {
if (i) parts[parts.length] = delim;
parts[parts.length] = (i in this) ? String(this[i]) : "";
}
}
else {
for (let i = 0; i < this.length; i++) {
parts[i] = (i in this) ? String(this[i]) : "";
}
}
return string.stringBuild(parts);
}
public push(this: any[]) {
const start = this.length;
for (let i = arguments.length - 1; i >= 0; i--) {
this[start + i] = arguments[i];
}
return arguments.length;
}
public pop(this: any[]) {
if (this.length === 0) return undefined;
else {
const res = this[this.length - 1];
this.length--;
return res;
}
}
public unshift(this: any[]) {
for (let i = this.length + arguments.length - 1; i >= arguments.length; i--) {
this[i] = this[i - arguments.length];
}
for (let i = 0; i < arguments.length; i++) {
this[i] = arguments[i];
}
return arguments.length;
}
public shift(this: any[]) {
if (this.length === 0) return undefined;
const tmp = this[0];
for (let i = 1; i < this.length; i++) {
this[i - 1] = this[i];
}
this.length--;
return tmp;
}
public concat(this: any[]) {
const res: any[] = [];
function add(arr: any) {
if (Array.isArray(arr) || arr != null && typeof arr === "object" && symbols.isConcatSpreadable in arr) {
const start = res.length;
res.length += arr.length;
for (let i = 0; i < res.length; i++) {
if (i in arr) res[start + i] = arr[i];
}
}
else res[res.length] = arr;
}
add(this);
for (let i = 0; i < arguments.length; i++) {
add(arguments[i]);
}
return res;
}
public slice(this: any[], start = 0, end = this.length) {
start = wrapI(start, this.length);
end = wrapI(end, this.length);
if (end <= start) return [];
const res: any[] = [];
res.length = end - start;
for (let i = 0; i < end - start; i++) {
res[i] = this[start + i];
}
return res;
}
public splice(this: any[], start = 0, count = this.length - start) {
const vals: any[] = []
for (let i = 0; i < arguments.length - 2; i++) vals[i] = arguments[i + 2];
start = limitI(wrapI(start, this.length), this.length);
count = limitI(wrapI(count, this.length), this.length - start);
const res: any[] = [];
const change = vals.length - count;
for (let i = start; i < start + count; i++) {
res[i - start] = this[i];
}
if (change < 0) {
for (let i = start - change; i < this.length; i++) {
this[i + change] = this[i];
}
this.length = this.length + change;
}
else {
for (let i = this.length - 1; i >= start - change; i--) {
this[i + change] = this[i];
}
}
for (let i = 0; i < vals.length; i++) {
this[i + start] = vals[i];
}
return res;
}
public map(this: any[], cb: Function, self?: any) {
const res = [];
res.length = this.length;
for (let i = 0; i < this.length; i++) {
if (i in this) res[i] = func.invoke(cb, self, [this[i], i, this]);
}
return res;
}
public filter(this: any[], cb: Function, self?: any) {
const res = [];
for (let i = 0; i < this.length; i++) {
if (i in this && func.invoke(cb, self, [this[i], i, this])) res[res.length] = this[i];
}
return res;
}
public reduce(this: any[], cb: Function, initial: any) {
let i = 0;
if (arguments.length <= 1) initial = this[i++];
for (; i < this.length; i++) {
initial = cb(initial, this[i], i, this);
}
return initial;
}
public some(this: any[], cb: Function, self?: any) {
for (let i = 0; i < this.length; i++) {
if (i in this && func.invoke(cb, self, [this[i], i, this])) return true;
}
return false;
}
public every(this: any[], cb: Function, self?: any) {
for (let i = 0; i < this.length; i++) {
if (i in this && !func.invoke(cb, self, [this[i], i, this])) return false;
}
return true;
}
public find(this: any[], cb: Function, self?: any) {
for (let i = 0; i < this.length; i++) {
if (i in this && func.invoke(cb, self, [this[i], i, this])) return this[i];
}
return undefined;
}
public indexOf(this: any[], val: any, start = 0) {
start |= 0;
if (start < 0) start = 0;
for (let i = start; i < this.length; i++) {
if (i in this && this[i] === val) return i;
}
return -1;
}
public lastIndexOf(this: any[], val: any, start = 0) {
start |= 0;
if (start < 0) start = 0;
for (let i = this.length - 1; i >= start; i--) {
if (i in this && this[i] === val) return i;
}
return -1;
}
public includes(this: any[], val: any) {
for (let i = 0; i < this.length; i++) {
if (i in this && this[i] === val) return true;
}
return false;
}
public sort(this: any[], cb?: Function) {
cb ||= (a: any, b: any) => {
if (String(a) < String(b)) return -1;
if (String(a) === String(b)) return 0;
return 1;
};
return object.sort(this, cb);
}
public reverse(this: any[]) {
const mid = this.length >> 1;
const end = this.length - 1;
for (let i = 0; i < mid; i++) {
const tmp = this[i];
this[i] = this[end - i];
this[end - i] = tmp;
}
return this;
}
public [symbols.iterator](this: any[]) {
let i = 0;
let arr: any[] | undefined = func.invoke(Array.prototype.slice, this, []);
return {
next() {
if (arr == null) return { done: true, value: undefined };
if (i >= arr.length) {
arr = undefined;
return { done: true, value: undefined };
}
while (true) {
const res = arr![i];
if (i in arr!) {
i++;
return { done: false, value: res };
}
else i++;
}
},
[symbols.iterator]() { return this; }
};
}
public constructor (len: unknown) {
if (arguments.length === 1 && typeof len === "number") {
const res: any[] = [];
res.length = len;
return res as any;
}
else {
const res: any[] = [];
res.length = arguments.length;
for (let i = 0; i < arguments.length; i++) {
res[i] = arguments[i];
}
return res as any;
}
}
public static isArray(val: any): val is any[] {
return object.isArray(val);
}
public static from(val: any, cb?: Function, self?: any): any[] {
if (symbols.iterator in val) {
const res = [];
const it = val[symbols.iterator]();
if (cb) {
for (let val = it.next(); !val.done; val = it.next()) {
res[res.length] = func.invoke(cb, self, [val.value]);
}
}
else {
for (let val = it.next(); !val.done; val = it.next()) {
res[res.length] = val.value;
}
}
return res;
}
else if ("length" in val) {
const res = [];
if (cb) {
for (let i = 0; i < val.length; i++) {
if (i in val) res[i] = func.invoke(cb, self, [val[i]]);
}
}
else {
for (let i = 0; i < val.length; i++) {
if (i in val) res[i] = val[i];
}
}
return res;
}
else if (val == null) throw new Error("Illegal argument");
else return [];
}
}
func.setCallable(Array, true);
func.setConstructable(Array, true);
return Array as any as typeof Array & ((value?: unknown) => object);
})();
export type Array = InstanceType<typeof Array>;