add more functions in stdlib, fix some issues

This commit is contained in:
TopchetoEU 2024-12-27 19:10:33 +02:00
parent f80266618c
commit 398d88c0a5
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
9 changed files with 87 additions and 37 deletions

View File

@ -1,10 +1,11 @@
import { Error } from "./errors.ts";
import { func, object, string } from "./primordials.ts"; import { func, object, string } from "./primordials.ts";
import { String } from "./string.ts"; import { String } from "./string.ts";
import { limitI, symbols, wrapI } from "./utils.ts"; import { limitI, symbols, wrapI } from "./utils.ts";
export const Array = (() => { export const Array = (() => {
class Array { class Array {
public forEach(this: any[], cb: (val: any, i: number, self: this[]) => void, self?: any) { public forEach(this: any[], cb: (val: any, i: number, self: this) => void, self?: any) {
for (let i = 0; i < this.length; i++) { for (let i = 0; i < this.length; i++) {
if (i in this) func.invoke(cb, self, [this[i], i, this]); if (i in this) func.invoke(cb, self, [this[i], i, this]);
} }
@ -98,7 +99,7 @@ export const Array = (() => {
const res: any[] = []; const res: any[] = [];
res.length = end - start; res.length = end - start;
for (let i = start; i < end; i++) { for (let i = 0; i < end - start; i++) {
res[i] = this[start + i]; res[i] = this[start + i];
} }
@ -163,6 +164,13 @@ export const Array = (() => {
return false; 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) { public find(this: any[], cb: Function, self?: any) {
for (let i = 0; i < this.length; i++) { for (let i = 0; i < this.length; i++) {
if (i in this && func.invoke(cb, self, [this[i], i, this])) return this[i]; if (i in this && func.invoke(cb, self, [this[i], i, this])) return this[i];
@ -170,6 +178,25 @@ export const Array = (() => {
return undefined; 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 sort(this: any[], cb?: Function) { public sort(this: any[], cb?: Function) {
cb ||= (a: any, b: any) => { cb ||= (a: any, b: any) => {

View File

@ -42,7 +42,7 @@ export const Function = (() => {
}; };
} }
public constructor (...args: string[]) { public constructor () {
const parts = ["(function anonymous("]; const parts = ["(function anonymous("];
for (let i = 0; i < arguments.length - 1; i++) { for (let i = 0; i < arguments.length - 1; i++) {
if (i > 0) parts[parts.length] = ","; if (i > 0) parts[parts.length] = ",";

View File

@ -1,5 +1,5 @@
import { Array } from "./array.ts"; import { Array } from "./array.ts";
import { func, map, object, symbol } from "./primordials.ts"; import { func, map, symbol } from "./primordials.ts";
import { symbols } from "./utils.ts"; import { symbols } from "./utils.ts";
const mapKey: unique symbol = symbol.makeSymbol("Map.impl") as any; const mapKey: unique symbol = symbol.makeSymbol("Map.impl") as any;

View File

@ -41,6 +41,16 @@ method("floor", function floor(val: number) {
return val - rem; return val - rem;
}); });
method("ceil", function floor(val: number) {
val = val - 0;
if (number.isNaN(val)) return number.NaN;
let rem = val % 1;
if (rem === 0) return val;
if (rem < 0) rem += 1;
return val + (1 - rem);
});
method("pow", function pow(a: number, b: number) { method("pow", function pow(a: number, b: number) {
return number.pow(a, b); return number.pow(a, b);

View File

@ -23,7 +23,7 @@ export const Number = (() => {
public static isFinite(value: number) { public static isFinite(value: number) {
value = unwrapThis(value, "number", Number, "Number.isFinite", "value"); value = unwrapThis(value, "number", Number, "Number.isFinite", "value");
if (value === undefined || value !== value) return false; if (value === undefined || value !== value) return false;
if (value === Infinity || value === -Infinity) return false; if (value === number.Infinity || value === -number.Infinity) return false;
return true; return true;
} }
public static isInteger(value: number) { public static isInteger(value: number) {
@ -51,14 +51,14 @@ export const Number = (() => {
else return number.parseInt(value + "", radix); else return number.parseInt(value + "", radix);
} }
public static readonly EPSILON: number; declare public static readonly EPSILON: number;
public static readonly MIN_SAFE_INTEGER: number; declare public static readonly MIN_SAFE_INTEGER: number;
public static readonly MAX_SAFE_INTEGER: number; declare public static readonly MAX_SAFE_INTEGER: number;
public static readonly POSITIVE_INFINITY: number; declare public static readonly POSITIVE_INFINITY: number;
public static readonly NEGATIVE_INFINITY: number; declare public static readonly NEGATIVE_INFINITY: number;
public static readonly NaN: number; declare public static readonly NaN: number;
public static readonly MAX_VALUE: number; declare public static readonly MAX_VALUE: number;
public static readonly MIN_VALUE: number; declare public static readonly MIN_VALUE: number;
} }
object.defineField(Number, "EPSILON", { c: false, e: false, w: false, v: 2.220446049250313e-16 }); object.defineField(Number, "EPSILON", { c: false, e: false, w: false, v: 2.220446049250313e-16 });

View File

@ -12,7 +12,7 @@ export const Object = (() => {
if (this === undefined) return "[object Undefined]"; if (this === undefined) return "[object Undefined]";
else if (this === null) return "[object Null]"; else if (this === null) return "[object Null]";
else if (typeof this === "object") { else if (typeof this === "object") {
if (symbols.toStringTag in this) return "[object " + this[symbols.toStringTag] + "]"; if (symbols.toStringTag in this) return "[object " + (this as any)[symbols.toStringTag] + "]";
else return "[object Object]"; else return "[object Object]";
} }
else if (typeof this === "number" || this instanceof Object) return "[object Object]"; else if (typeof this === "number" || this instanceof Object) return "[object Object]";
@ -84,8 +84,8 @@ export const Object = (() => {
return obj; return obj;
} }
public static defineProperties(obj: object, desc: PropertyDescriptorMap) { public static defineProperties(obj: object, desc: PropertyDescriptorMap) {
const keys = object.getOwnMembers(desc, false); const keys = object.getOwnMembers(desc, false) as ((keyof typeof obj) & string)[];
const symbols = object.getOwnSymbolMembers(desc, false); const symbols = object.getOwnSymbolMembers(desc, false) as ((keyof typeof obj) & symbol)[];
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
Object.defineProperty(obj, keys[i], desc[keys[i]]); Object.defineProperty(obj, keys[i], desc[keys[i]]);

View File

@ -1,6 +1,6 @@
import { func, regex, symbol } from "./primordials.ts"; import { func, regex, symbol } from "./primordials.ts";
import { String } from "./string.ts"; import { String } from "./string.ts";
import { ReplaceRange } from "./utils.ts"; import { type ReplaceRange } from "./utils.ts";
import { applyReplaces } from "./utils.ts"; import { applyReplaces } from "./utils.ts";
import { applySplits } from "./utils.ts"; import { applySplits } from "./utils.ts";
import { symbols } from "./utils.ts"; import { symbols } from "./utils.ts";
@ -8,22 +8,24 @@ import { symbols } from "./utils.ts";
const regexKey: unique symbol = symbol.makeSymbol("RegExp.impl") as any; const regexKey: unique symbol = symbol.makeSymbol("RegExp.impl") as any;
export class RegExp { export class RegExp {
private [regexKey]: InstanceType<typeof regex>; private [regexKey]!: InstanceType<typeof regex>;
public readonly source: string; public readonly source!: string;
public readonly flags: string; public readonly flags!: string;
public lastIndex = 0; public lastIndex = 0;
public readonly indices: boolean; public readonly indices!: boolean;
public readonly global: boolean; public readonly global!: boolean;
public readonly ignoreCase: boolean; public readonly ignoreCase!: boolean;
public readonly multiline: boolean; public readonly multiline!: boolean;
public readonly dotall: boolean; public readonly dotall!: boolean;
public readonly unicode: boolean; public readonly unicode!: boolean;
public readonly unicodeSets: boolean; public readonly unicodeSets!: boolean;
public readonly sticky: boolean; public readonly sticky!: boolean;
public constructor(source: any, flags = "") {
if (func.invokeType(arguments, this) === "call") return new RegExp(source, flags);
public constructor(source: any, flags: string) {
source = this.source = String(typeof source === "object" && "source" in source ? source.source : source); source = this.source = String(typeof source === "object" && "source" in source ? source.source : source);
flags = String(flags); flags = String(flags);
@ -134,4 +136,3 @@ export class RegExp {
return applyReplaces(target, matches, replacer, regex.groupCount() + 1); return applyReplaces(target, matches, replacer, regex.groupCount() + 1);
} }
} }
func.setCallable(RegExp, false);

View File

@ -1,6 +1,7 @@
import { TypeError } from "./errors.ts";
import { func, number, regex, string } from "./primordials.ts"; import { func, number, regex, string } from "./primordials.ts";
import { RegExp } from "./regex.ts"; import { RegExp } from "./regex.ts";
import { applyReplaces, applySplits, limitI, ReplaceRange, symbols, unwrapThis, valueKey, wrapI } from "./utils.ts"; import { applyReplaces, applySplits, limitI, type ReplaceRange, symbols, unwrapThis, valueKey, wrapI } from "./utils.ts";
const trimStartRegex = new regex("^\\s+", false, false, false, false, false); const trimStartRegex = new regex("^\\s+", false, false, false, false, false);
const trimEndRegex = new regex("\\s+$", false, false, false, false, false); const trimEndRegex = new regex("\\s+$", false, false, false, false, false);
@ -12,7 +13,7 @@ export const String = (() => {
public at(index: number) { public at(index: number) {
throw "Not implemented :/"; throw "Not implemented :/";
return unwrapThis(this, "string", String, "String.prototype.at")[index]; return unwrapThis(this, "string", String, "String.prototype.at")[index];
}; }
public toString() { public toString() {
return unwrapThis(this, "string", String, "String.prototype.toString"); return unwrapThis(this, "string", String, "String.prototype.toString");
} }
@ -24,6 +25,16 @@ export const String = (() => {
const self = unwrapThis(this, "string", String, "String.prototype.indexOf"); const self = unwrapThis(this, "string", String, "String.prototype.indexOf");
return string.indexOf(self, (String as any)(search), +offset, false) >= 0; return string.indexOf(self, (String as any)(search), +offset, false) >= 0;
} }
public startsWith(search: string) {
const self = unwrapThis(this, "string", String, "String.prototype.indexOf");
if (self.length < search.length) return false;
return string.substring(self, 0, search.length) === search;
}
public endsWith(search: string) {
const self = unwrapThis(this, "string", String, "String.prototype.indexOf");
if (self.length < search.length) return false;
return string.substring(self, self.length - search.length, self.length) === search;
}
public indexOf(search: string, offset = 0) { public indexOf(search: string, offset = 0) {
const self = unwrapThis(this, "string", String, "String.prototype.indexOf"); const self = unwrapThis(this, "string", String, "String.prototype.indexOf");
@ -123,10 +134,11 @@ export const String = (() => {
return applyReplaces(self, matches, replacer, false); return applyReplaces(self, matches, replacer, false);
} }
public slice(this: string, start = 0, end = this.length) { public slice(start = 0, end?: number) {
const self = unwrapThis(this, "string", String, "String.prototype.slice"); const self = unwrapThis(this, "string", String, "String.prototype.slice");
start = limitI(wrapI(start, this.length), this.length); if (end === undefined) end = self.length;
end = limitI(wrapI(end, this.length), this.length); start = limitI(wrapI(start, self.length), self.length);
end = limitI(wrapI(end, self.length), self.length);
if (end <= start) return ""; if (end <= start) return "";
return string.substring(self, start, end); return string.substring(self, start, end);

View File

@ -195,12 +195,12 @@ export function applySplits(text: string, limit: number | undefined, next: (offs
const res: string[] = []; const res: string[] = [];
while (true) { while (true) {
if (limit != null && res.length >= limit) break; if (limit != null && limit >= 0 && res.length >= limit) break;
const curr = next(offset); const curr = next(offset);
if (curr == null) { if (curr == null) {
if (!lastEmpty) res[res.length] = string.substring(text, lastEnd, text.length); if (!lastEmpty || !res.length) res[res.length] = string.substring(text, lastEnd, text.length);
break; break;
} }