From 74f08b74834692cd000a0be92e64717150e06fa2 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Sat, 28 Dec 2024 13:16:54 +0200 Subject: [PATCH] small stdlib improvements --- src/lib/libs/_entry.ts | 5 +++ src/lib/libs/array.ts | 29 ++++++++++++ src/lib/libs/console.ts | 11 +++++ src/lib/libs/math.ts | 3 ++ src/lib/libs/object.ts | 29 +++++++----- src/lib/libs/polyfills/createClass.js | 17 +++++-- src/lib/libs/primordials.ts | 13 ++++-- src/lib/libs/string.ts | 64 +++++++++++++++++++++++---- 8 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 src/lib/libs/console.ts diff --git a/src/lib/libs/_entry.ts b/src/lib/libs/_entry.ts index 39013fd..7932b68 100644 --- a/src/lib/libs/_entry.ts +++ b/src/lib/libs/_entry.ts @@ -13,6 +13,7 @@ import { Date } from "./date.ts"; import { Math as _Math } from "./math.ts"; import { Set, WeakSet } from "./set.ts"; import { JSON } from "./json.ts"; +import { console } from "./console.ts"; import { encodeURI, encodeURIComponent } from "./url.ts"; import { Promise } from "./promise.ts"; @@ -27,6 +28,8 @@ function fixup(clazz: T) { return clazz; } +object.setPrototype(target, Object.prototype); + object.defineField(target, "undefined", { e: false, c: false, w: false, v: void 0 }); target.Symbol = fixup(Symbol); @@ -52,6 +55,8 @@ target.Date = fixup(Date); target.Promise = fixup(Promise); target.Math = object.setPrototype(_Math, Object.prototype); target.JSON = object.setPrototype(JSON, Object.prototype); +target.console = object.setPrototype(console, Object.prototype); +target.TYPED_ARRAY_SUPPORT = false; target.parseInt = Number.parseInt; target.parseFloat = Number.parseFloat; diff --git a/src/lib/libs/array.ts b/src/lib/libs/array.ts index ed1a11a..84d7967 100644 --- a/src/lib/libs/array.ts +++ b/src/lib/libs/array.ts @@ -157,6 +157,16 @@ export const Array = (() => { 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; @@ -197,6 +207,13 @@ export const Array = (() => { return -1; } + public includes(this: any[], val: any) { + for (let i = 0; i < this.length; i++) { + if (i in this && this[i] === val) return i; + } + + return false; + } public sort(this: any[], cb?: Function) { cb ||= (a: any, b: any) => { @@ -207,6 +224,18 @@ export const Array = (() => { 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; diff --git a/src/lib/libs/console.ts b/src/lib/libs/console.ts new file mode 100644 index 0000000..be5b7a9 --- /dev/null +++ b/src/lib/libs/console.ts @@ -0,0 +1,11 @@ +import { func, json, object } from "./primordials"; + +export const console = {}; + +function method(name: string, func: Function) { + object.defineField(console, name, { c: true, e: false, w: true, v: func }); +} + +method("log", function log() { + func.invoke(print, null, arguments as any); +}); diff --git a/src/lib/libs/math.ts b/src/lib/libs/math.ts index e548c7a..63e0b3f 100644 --- a/src/lib/libs/math.ts +++ b/src/lib/libs/math.ts @@ -55,3 +55,6 @@ method("ceil", function floor(val: number) { method("pow", function pow(a: number, b: number) { return number.pow(a, b); }); +method("log", function log(val: number) { + return number.log(val); +}); \ No newline at end of file diff --git a/src/lib/libs/object.ts b/src/lib/libs/object.ts index b08bac4..4e5e575 100644 --- a/src/lib/libs/object.ts +++ b/src/lib/libs/object.ts @@ -13,9 +13,10 @@ export const Object = (() => { else if (this === null) return "[object Null]"; else if (typeof this === "object") { if (symbols.toStringTag in this) return "[object " + (this as any)[symbols.toStringTag] + "]"; + else if (object.isArray(this)) return "[object Array]"; else return "[object Object]"; } - else if (typeof this === "number" || this instanceof Object) return "[object Object]"; + else if (typeof this === "number" || this instanceof Number) return "[object Number]"; else if (typeof this === "symbol" || this instanceof Symbol) return "[object Symbol]"; else if (typeof this === "string" || this instanceof String) return "[object String]"; else if (typeof this === "boolean" || this instanceof Boolean) return "[object Boolean]"; @@ -46,6 +47,12 @@ export const Object = (() => { public static getOwnPropertyDescriptor(obj: object, key: any) { return object.getOwnMember(obj, key); } + public static getOwnPropertyNames(obj: object): string[] { + return object.getOwnMembers(obj, false); + } + public static getOwnPropertySymbols(obj: object): symbol[] { + return object.getOwnSymbolMembers(obj, false); + } public static defineProperty(obj: object, key: string | symbol, desc: PropertyDescriptor) { if (obj === null || typeof obj !== "function" && typeof obj !== "object") { @@ -84,8 +91,8 @@ export const Object = (() => { return obj; } public static defineProperties(obj: object, desc: PropertyDescriptorMap) { - const keys = object.getOwnMembers(desc, false) as ((keyof typeof obj) & string)[]; - const symbols = object.getOwnSymbolMembers(desc, false) as ((keyof typeof obj) & symbol)[]; + const keys = object.getOwnMembers(desc, true) as ((keyof typeof obj) & string)[]; + const symbols = object.getOwnSymbolMembers(desc, true) as ((keyof typeof obj) & symbol)[]; for (let i = 0; i < keys.length; i++) { Object.defineProperty(obj, keys[i], desc[keys[i]]); @@ -119,7 +126,6 @@ export const Object = (() => { return target; } - public static setPrototypeOf(obj: object, proto: object | null) { object.setPrototype(obj, proto!); } @@ -129,8 +135,8 @@ export const Object = (() => { public static keys(obj: any) { const res: any[] = []; - const keys = object.getOwnMembers(obj, false); - const symbols = object.getOwnSymbolMembers(obj, false); + const keys = object.getOwnMembers(obj, true); + const symbols = object.getOwnSymbolMembers(obj, true); for (let i = 0; i < keys.length; i++) { res[res.length] = keys[i]; @@ -143,8 +149,8 @@ export const Object = (() => { } public static values(obj: any) { const res: any[] = []; - const keys = object.getOwnMembers(obj, false); - const symbols = object.getOwnSymbolMembers(obj, false); + const keys = object.getOwnMembers(obj, true); + const symbols = object.getOwnSymbolMembers(obj, true); for (let i = 0; i < keys.length; i++) { res[res.length] = obj[keys[i]]; @@ -157,8 +163,8 @@ export const Object = (() => { } public static entries(obj: any) { const res: [any, any][] = []; - const keys = object.getOwnMembers(obj, false); - const symbols = object.getOwnSymbolMembers(obj, false); + const keys = object.getOwnMembers(obj, true); + const symbols = object.getOwnSymbolMembers(obj, true); for (let i = 0; i < keys.length; i++) { res[res.length] = [keys[i], obj[keys[i]]]; @@ -172,12 +178,15 @@ export const Object = (() => { public static preventExtensions(obj: object) { object.preventExt(obj); + return obj; } public static seal(obj: object) { object.seal(obj); + return obj; } public static freeze(obj: object) { object.freeze(obj); + return obj; } } diff --git a/src/lib/libs/polyfills/createClass.js b/src/lib/libs/polyfills/createClass.js index 76fa6e0..2876e9f 100644 --- a/src/lib/libs/polyfills/createClass.js +++ b/src/lib/libs/polyfills/createClass.js @@ -5,19 +5,28 @@ function _defineProperties(target, arr) { for (var i = 0; i < arr.length; i++) { var desc = arr[i]; var res; - + var w, e, c; + + c = desc.configurable; + if (c == null) c = true; + e = desc.enumerable; + if (e == null) e = false; + if ("value" in desc) { - res = object.defineField(target, desc.key, { w: desc.writable || true, e: desc.enumerable || true, c: desc.configurable || true, v: desc.value }); + w = desc.writable; + if (w == null) w = true; + + if (desc.writable == null) + res = object.defineField(target, desc.key, { w: !!w, e: !!e, c: !!c, v: desc.value }); } else { - res = object.defineProperty(target, desc.key, { e: desc.enumerable || true, c: desc.configurable || true, g: desc.get, s: desc.set }); + res = object.defineProperty(target, desc.key, { e: !!e, c: !!c, g: desc.get, s: desc.set }); } if (!res) throw "Couldn't set property"; } } -/* __#PURE__ */ export default function _createClass(clazz, instance, nonInstance) { _defineProperties(clazz.prototype, instance); _defineProperties(clazz, nonInstance); diff --git a/src/lib/libs/primordials.ts b/src/lib/libs/primordials.ts index 55b4dbe..b042611 100644 --- a/src/lib/libs/primordials.ts +++ b/src/lib/libs/primordials.ts @@ -5,13 +5,17 @@ export interface SymbolPrimordials { getSymbolDescription(symbol: symbol): string; } export interface NumberPrimordials { + NaN: number; + Infinity: number; + PI: number; + E: number; + parseInt(raw: string | number, radix?: number): number; parseFloat(raw: string | number): number; isNaN(num: number): boolean; - NaN: number; - Infinity: number; pow(a: number, b: number): number; + log(val: number): number; } export interface StringPrimordials { stringBuild(parts: string[]): string; @@ -32,12 +36,13 @@ export interface ObjectPrimordials { getOwnSymbolMembers(obj: object, onlyEnumerable: boolean): symbol[]; getPrototype(obj: object): object | undefined; setPrototype(obj: object, proto?: object): object; - isArray(obj: any[]): boolean; - preventExt(obj: object): void; seal(obj: object): void; freeze(obj: object): void; + isArray(obj: any): obj is any[]; + subarray(arr: any[], start: number, end: number): any[]; + memcpy(src: any[], dst: any[], srcI: number, dstI: number, n: number): void; sort(arr: any[], cb: Function): any[]; } diff --git a/src/lib/libs/string.ts b/src/lib/libs/string.ts index 9477401..1aed997 100644 --- a/src/lib/libs/string.ts +++ b/src/lib/libs/string.ts @@ -72,6 +72,13 @@ export const String = (() => { return string.substring(self, 0, endI); } + public trimLeft() { + return func.invoke(String.prototype.trimStart, this, []); + } + public trimRight() { + return func.invoke(String.prototype.trimEnd, this, []); + } + public charAt(i: number) { const self = unwrapThis(this, "string", String, "String.prototype.charAt"); return self[i]; @@ -133,6 +140,16 @@ export const String = (() => { return applyReplaces(self, matches, replacer, false); } + public repeat(n: number) { + const self = unwrapThis(this, "string", String, "String.prototype.replaceAll"); + const res: string[] = []; + + for (let i = 0; i < n; i++) { + res[i] = self; + } + + return string.stringBuild(res); + } public slice(start = 0, end?: number) { const self = unwrapThis(this, "string", String, "String.prototype.slice"); @@ -143,32 +160,63 @@ export const String = (() => { if (end <= start) return ""; return string.substring(self, start, end); } - public substring(this: string, start = 0, end = this.length) { + public substring(start = 0, end?: number) { const self = unwrapThis(this, "string", String, "String.prototype.substring"); - start = limitI(start, this.length); - end = limitI(end, this.length); + if (end === undefined) end = self.length; + start = limitI(start, self.length); + end = limitI(end, self.length); if (end <= start) return ""; return string.substring(self, start, end); } - public substr(this: string, start = 0, count = this.length - start) { + public substr(start = 0, count?: number) { const self = unwrapThis(this, "string", String, "String.prototype.substr"); - start = limitI(start, this.length); - count = limitI(count, this.length - start); + count = self.length - start; + start = limitI(start, self.length); + count = limitI(count, self.length - start); if (count <= 0) return ""; return string.substring(self, start, count + start); } + public concat() { + const self = unwrapThis(this, "string", String, "String.prototype.concat"); + const parts = [self]; + for (let i = 0; i < arguments.length; i++) { + parts[i + 1] = (String as any)(arguments[i]); + } - public toLowerCase(this: string) { + return string.stringBuild(parts); + } + + public toLowerCase() { const self = unwrapThis(this, "string", String, "String.prototype.toLowerCase"); return string.lower(self); } - public toUpperCase(this: string) { + public toUpperCase() { const self = unwrapThis(this, "string", String, "String.prototype.toLowerCase"); return string.upper(self); } + public match(regex: RegExp) { + const self = unwrapThis(this, "string", String, "String.prototype.match"); + if (!(regex instanceof RegExp)) throw new TypeError("Regexp expected for String.prototype.match"); + + if (regex.global) { + let matches: string[] | null = null; + + while (true) { + const match = regex.exec(self); + if (match == null) break; + + matches ||= []; + matches[matches.length] = match[0]; + } + + return matches; + } + else return regex.exec(self); + } + public [symbols.iterator]() { var i = 0; var arr: string | undefined = unwrapThis(this, "string", String, "String.prototype[Symbol.iterator]");