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 { String } from "./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) {
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]);
}
@ -98,7 +99,7 @@ export const Array = (() => {
const res: any[] = [];
res.length = end - start;
for (let i = start; i < end; i++) {
for (let i = 0; i < end - start; i++) {
res[i] = this[start + i];
}
@ -163,6 +164,13 @@ export const Array = (() => {
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];
@ -170,6 +178,25 @@ export const Array = (() => {
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) {
cb ||= (a: any, b: any) => {

View File

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

View File

@ -1,5 +1,5 @@
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";
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;
});
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) {
return number.pow(a, b);

View File

@ -23,7 +23,7 @@ export const Number = (() => {
public static isFinite(value: number) {
value = unwrapThis(value, "number", Number, "Number.isFinite", "value");
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;
}
public static isInteger(value: number) {
@ -51,14 +51,14 @@ export const Number = (() => {
else return number.parseInt(value + "", radix);
}
public static readonly EPSILON: number;
public static readonly MIN_SAFE_INTEGER: number;
public static readonly MAX_SAFE_INTEGER: number;
public static readonly POSITIVE_INFINITY: number;
public static readonly NEGATIVE_INFINITY: number;
public static readonly NaN: number;
public static readonly MAX_VALUE: number;
public static readonly MIN_VALUE: number;
declare public static readonly EPSILON: number;
declare public static readonly MIN_SAFE_INTEGER: number;
declare public static readonly MAX_SAFE_INTEGER: number;
declare public static readonly POSITIVE_INFINITY: number;
declare public static readonly NEGATIVE_INFINITY: number;
declare public static readonly NaN: number;
declare public static readonly MAX_VALUE: number;
declare public static readonly MIN_VALUE: number;
}
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]";
else if (this === null) return "[object Null]";
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 if (typeof this === "number" || this instanceof Object) return "[object Object]";
@ -84,8 +84,8 @@ export const Object = (() => {
return obj;
}
public static defineProperties(obj: object, desc: PropertyDescriptorMap) {
const keys = object.getOwnMembers(desc, false);
const symbols = object.getOwnSymbolMembers(desc, false);
const keys = object.getOwnMembers(desc, false) as ((keyof typeof obj) & string)[];
const symbols = object.getOwnSymbolMembers(desc, false) as ((keyof typeof obj) & symbol)[];
for (let i = 0; i < keys.length; i++) {
Object.defineProperty(obj, keys[i], desc[keys[i]]);

View File

@ -1,6 +1,6 @@
import { func, regex, symbol } from "./primordials.ts";
import { String } from "./string.ts";
import { ReplaceRange } from "./utils.ts";
import { type ReplaceRange } from "./utils.ts";
import { applyReplaces } from "./utils.ts";
import { applySplits } 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;
export class RegExp {
private [regexKey]: InstanceType<typeof regex>;
private [regexKey]!: InstanceType<typeof regex>;
public readonly source: string;
public readonly flags: string;
public readonly source!: string;
public readonly flags!: string;
public lastIndex = 0;
public readonly indices: boolean;
public readonly global: boolean;
public readonly ignoreCase: boolean;
public readonly multiline: boolean;
public readonly dotall: boolean;
public readonly unicode: boolean;
public readonly unicodeSets: boolean;
public readonly sticky: boolean;
public readonly indices!: boolean;
public readonly global!: boolean;
public readonly ignoreCase!: boolean;
public readonly multiline!: boolean;
public readonly dotall!: boolean;
public readonly unicode!: boolean;
public readonly unicodeSets!: 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);
flags = String(flags);
@ -134,4 +136,3 @@ export class RegExp {
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 { 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 trimEndRegex = new regex("\\s+$", false, false, false, false, false);
@ -12,7 +13,7 @@ export const String = (() => {
public at(index: number) {
throw "Not implemented :/";
return unwrapThis(this, "string", String, "String.prototype.at")[index];
};
}
public 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");
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) {
const self = unwrapThis(this, "string", String, "String.prototype.indexOf");
@ -123,10 +134,11 @@ export const String = (() => {
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");
start = limitI(wrapI(start, this.length), this.length);
end = limitI(wrapI(end, this.length), this.length);
if (end === undefined) end = self.length;
start = limitI(wrapI(start, self.length), self.length);
end = limitI(wrapI(end, self.length), self.length);
if (end <= start) return "";
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[] = [];
while (true) {
if (limit != null && res.length >= limit) break;
if (limit != null && limit >= 0 && res.length >= limit) break;
const curr = next(offset);
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;
}