add more functions in stdlib, fix some issues
This commit is contained in:
parent
f80266618c
commit
398d88c0a5
@ -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) => {
|
||||||
|
@ -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] = ",";
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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 });
|
||||||
|
@ -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]]);
|
||||||
|
@ -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);
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user