feat: implement a lot of stdlibs
This commit is contained in:
parent
6fac295b99
commit
239d0ae8d7
@ -1,36 +1,52 @@
|
||||
import { Boolean } from "./boolean.ts";
|
||||
import { object, setGlobalPrototypes, target } from "./primordials.ts";
|
||||
import { Error, RangeError, SyntaxError, TypeError } from "./errors.ts";
|
||||
import { Boolean } from "./boolean.ts";
|
||||
import { Function } from "./function.ts";
|
||||
import { Number } from "./number.ts";
|
||||
import { Object } from "./object.ts";
|
||||
import { object, setGlobalPrototypes, target } from "./primordials.ts";
|
||||
import { String } from "./string.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
import { Array } from "./array.ts";
|
||||
import { Map } from "./map.ts";
|
||||
import { Map, WeakMap } from "./map.ts";
|
||||
import { RegExp } from "./regex.ts";
|
||||
import { Date } from "./date.ts";
|
||||
import { Math as _Math } from "./math.ts";
|
||||
import { Set, WeakSet } from "./set.ts";
|
||||
|
||||
declare global {
|
||||
function print(...args: any[]): void;
|
||||
function measure(func: Function): void;
|
||||
}
|
||||
|
||||
object.defineField(target, "undefined", false, false, false, undefined);
|
||||
function fixup<T extends Function>(clazz: T) {
|
||||
object.setPrototype(clazz, Function.prototype);
|
||||
object.setPrototype(clazz.prototype, Object.prototype);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
target.Symbol = Symbol;
|
||||
target.Number = Number;
|
||||
target.String = String;
|
||||
target.Boolean = Boolean;
|
||||
object.defineField(target, "undefined", { e: false, c: false, w: false, v: void 0 });
|
||||
|
||||
target.Symbol = fixup(Symbol);
|
||||
target.Number = fixup(Number);
|
||||
target.String = fixup(String);
|
||||
target.Boolean = fixup(Boolean);
|
||||
|
||||
target.Object = Object;
|
||||
target.Function = Function;
|
||||
target.Array = Array;
|
||||
target.Function = fixup(Function);
|
||||
target.Array = fixup(Array);
|
||||
|
||||
target.Error = Error;
|
||||
target.Error = fixup(Error);
|
||||
target.RangeError = RangeError;
|
||||
target.SyntaxError = SyntaxError;
|
||||
target.TypeError = TypeError;
|
||||
|
||||
target.Map = Map;
|
||||
target.Map = fixup(Map);
|
||||
target.WeakMap = fixup(WeakMap);
|
||||
target.Set = fixup(Set);
|
||||
target.WeakSet = fixup(WeakSet);
|
||||
target.RegExp = fixup(RegExp);
|
||||
target.Date = fixup(Date);
|
||||
target.Math = object.setPrototype(_Math, Object.prototype);
|
||||
|
||||
target.parseInt = Number.parseInt;
|
||||
target.parseFloat = Number.parseFloat;
|
||||
@ -38,8 +54,6 @@ target.NaN = Number.NaN;
|
||||
target.Infinity = Number.POSITIVE_INFINITY;
|
||||
|
||||
|
||||
target.RegExp = RegExp;
|
||||
|
||||
setGlobalPrototypes({
|
||||
string: String.prototype,
|
||||
number: Number.prototype,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { func, object } from "./primordials.ts";
|
||||
import { Symbol } from "./symbol.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 {
|
||||
@ -8,15 +9,133 @@ export const Array = (() => {
|
||||
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]) : "";
|
||||
}
|
||||
}
|
||||
|
||||
public [Symbol.iterator](this: any[]) {
|
||||
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 concat(this: any[]) {
|
||||
const res: any[] = [];
|
||||
|
||||
function add(arr: any) {
|
||||
if (Array.isArray(arr) || 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 = start; i < end; i++) {
|
||||
res[i] = this[start + i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
public splice(this: any[], start = 0, count = this.length - start, ...vals: any[]) {
|
||||
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 < arguments.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 < arguments.length; i++) {
|
||||
if (i in this && func.invoke(cb, self, [this[i], i, this])) res[res.length] = this[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
public some(this: any[], cb: Function, self?: any) {
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
if (i in this && func.invoke(cb, self, [this[i], i, this])) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public [symbols.iterator](this: any[]) {
|
||||
let i = 0;
|
||||
let arr: any[] | undefined = this;
|
||||
|
||||
return {
|
||||
next() {
|
||||
if (arr == null) return { done: true, value: undefined };
|
||||
if (i > arr.length) {
|
||||
if (i >= arr.length) {
|
||||
arr = undefined;
|
||||
return { done: true, value: undefined };
|
||||
}
|
||||
@ -26,7 +145,7 @@ export const Array = (() => {
|
||||
return { done: false, value: val };
|
||||
}
|
||||
},
|
||||
[Symbol.iterator]() { return this; }
|
||||
[symbols.iterator]() { return this; }
|
||||
};
|
||||
}
|
||||
|
||||
@ -40,8 +159,45 @@ export const Array = (() => {
|
||||
else throw new Error("Spreading not implemented");
|
||||
}
|
||||
|
||||
public static isArray(val: any[]) {
|
||||
object.isArray(val);
|
||||
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 [];
|
||||
}
|
||||
}
|
||||
|
||||
|
20
src/lib/libs/date.ts
Normal file
20
src/lib/libs/date.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { now, symbol } from "./primordials.ts";
|
||||
|
||||
const timeKey: unique symbol = symbol.makeSymbol("") as any;
|
||||
|
||||
export const Date = (() => {
|
||||
class Date {
|
||||
[timeKey]!: number;
|
||||
|
||||
public constructor() {
|
||||
|
||||
}
|
||||
|
||||
public static now() {
|
||||
return now();
|
||||
}
|
||||
};
|
||||
|
||||
return Date as any as typeof Date & ((val?: unknown) => string);
|
||||
})();
|
||||
export type Date = InstanceType<typeof Date>;
|
@ -18,22 +18,22 @@ export class Error {
|
||||
this.message = String(msg);
|
||||
}
|
||||
}
|
||||
object.defineField(Error.prototype, "name", true, false, true, "Error");
|
||||
object.defineField(Error.prototype, "message", true, false, true, "");
|
||||
object.defineField(Error.prototype, "name", { c: true, e: false, w: true, v: "Error" });
|
||||
object.defineField(Error.prototype, "message", { c: true, e: false, w: true, v: "" });
|
||||
func.setCallable(Error, true);
|
||||
func.setConstructable(Error, true);
|
||||
|
||||
export class SyntaxError extends Error { }
|
||||
object.defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError");
|
||||
object.defineField(SyntaxError.prototype, "name", { c: true, e: false, w: true, v: "SyntaxError" });
|
||||
func.setCallable(SyntaxError, true);
|
||||
func.setConstructable(SyntaxError, true);
|
||||
|
||||
export class TypeError extends Error { }
|
||||
object.defineField(TypeError.prototype, "name", true, false, true, "TypeError");
|
||||
object.defineField(TypeError.prototype, "name", { c: true, e: false, w: true, v: "TypeError" });
|
||||
func.setCallable(TypeError, true);
|
||||
func.setConstructable(TypeError, true);
|
||||
|
||||
export class RangeError extends Error { }
|
||||
object.defineField(RangeError.prototype, "name", true, false, true, "RangeError");
|
||||
object.defineField(RangeError.prototype, "name", { c: true, e: false, w: true, v: "RangeError" });
|
||||
func.setCallable(RangeError, true);
|
||||
func.setConstructable(RangeError, true);
|
||||
|
@ -17,9 +17,30 @@ export const Function = (() => {
|
||||
public apply(this: (...args: any) => any, self: any, args: any[]) {
|
||||
return func.invoke(this, self, args);
|
||||
}
|
||||
public call(this: (...args: any) => any, self: any, ...args: any[]) {
|
||||
public call(this: (...args: any) => any, self: any) {
|
||||
const args: any[] = [];
|
||||
for (let i = arguments.length - 1; i >= 1; i--) args[i - 1] = arguments[i];
|
||||
return func.invoke(this, self, args);
|
||||
}
|
||||
public bind(this: (...args: any) => any, self: any) {
|
||||
const cb = this;
|
||||
if (arguments.length === 0) return function (this: any) { return func.invoke(cb, this, arguments as any) };
|
||||
if (arguments.length <= 1) return function () { return func.invoke(cb, self, arguments as any); }
|
||||
|
||||
const base: any[] = [];
|
||||
const offset = arguments.length - 1;
|
||||
base.length = offset;
|
||||
|
||||
for (let i = 0; i < offset; i++) base[i] = arguments[i + 1];
|
||||
|
||||
return function () {
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
base[offset + i] = arguments[i];
|
||||
}
|
||||
|
||||
return func.invoke(cb, self, base);
|
||||
};
|
||||
}
|
||||
|
||||
public constructor (...args: string[]) {
|
||||
const parts = ["(function anonymous("];
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { func, map } from "./primordials.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
import { Array } from "./array.ts";
|
||||
import { func, map, object, symbol } from "./primordials.ts";
|
||||
import { symbols } from "./utils.ts";
|
||||
|
||||
const mapKey: unique symbol = Symbol("Map.impl") as any;
|
||||
const mapKey: unique symbol = symbol.makeSymbol("Map.impl") as any;
|
||||
|
||||
export class Map<K, V> {
|
||||
private [mapKey]: InstanceType<typeof map>;
|
||||
@ -23,6 +24,9 @@ export class Map<K, V> {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public clear() {
|
||||
this[mapKey].clear();
|
||||
}
|
||||
|
||||
public keys(): K[] {
|
||||
return this[mapKey].keys();
|
||||
@ -42,20 +46,79 @@ export class Map<K, V> {
|
||||
return res;
|
||||
}
|
||||
|
||||
public [Symbol.iterator](): Iterator<[K, V]> {
|
||||
return func.invoke(Array.prototype[Symbol.iterator as any], this.entries(), []) as any;
|
||||
public forEach(cb: Function, self?: any) {
|
||||
const entries = this.entries();
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
func.invoke(cb, self, [entries[i][1], entries[i][0], this]);
|
||||
}
|
||||
}
|
||||
|
||||
public [symbols.iterator](): Iterator<[K, V]> {
|
||||
return func.invoke(Array.prototype[symbols.iterator], this.entries(), []) as any;
|
||||
}
|
||||
|
||||
public constructor(iterable?: Iterable<[K, V]>) {
|
||||
const _map = this[mapKey] = new map();
|
||||
|
||||
if (iterable != null) {
|
||||
const it = (iterable as any)[Symbol.iterator]();
|
||||
for (let val = it.next(); !val.done; val = it.next()) {
|
||||
_map.set(val.value[0], val.value[1]);
|
||||
if (Array.isArray(iterable)) {
|
||||
for (let i = 0; i < iterable.length; i++) {
|
||||
if (!(i in iterable)) continue;
|
||||
_map.set(iterable[i][0], iterable[i][1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const it = (iterable as any)[symbols.iterator]();
|
||||
for (let val = it.next(); !val.done; val = it.next()) {
|
||||
_map.set(val.value[0], val.value[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export class WeakMap<K, V> {
|
||||
private [mapKey]: InstanceType<typeof map>;
|
||||
|
||||
public get(key: K): V {
|
||||
return this[mapKey].get(key);
|
||||
}
|
||||
public has(key: K): boolean {
|
||||
return this[mapKey].has(key);
|
||||
}
|
||||
public set(key: K, val: V) {
|
||||
this[mapKey].set(key, val);
|
||||
return this;
|
||||
}
|
||||
public delete(key: K): boolean {
|
||||
if (!this[mapKey].has(key)) return false;
|
||||
else {
|
||||
this[mapKey].delete(key);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public clear() {
|
||||
this[mapKey].clear();
|
||||
}
|
||||
|
||||
public constructor(iterable?: Iterable<[K, V]>) {
|
||||
const _map = this[mapKey] = new map(true);
|
||||
|
||||
if (iterable != null) {
|
||||
if (Array.isArray(iterable)) {
|
||||
for (let i = 0; i < iterable.length; i++) {
|
||||
if (!(i in iterable)) continue;
|
||||
_map.set(iterable[i][0], iterable[i][1]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const it = (iterable as any)[symbols.iterator]();
|
||||
for (let val = it.next(); !val.done; val = it.next()) {
|
||||
_map.set(val.value[0], val.value[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func.setCallable(Map, false);
|
||||
func.setCallable(WeakMap, false);
|
||||
|
27
src/lib/libs/math.ts
Normal file
27
src/lib/libs/math.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { number, object } from "./primordials";
|
||||
|
||||
export const Math = {};
|
||||
|
||||
function method(name: string, func: Function) {
|
||||
object.defineField(Math, name, { c: true, e: false, w: true, v: func });
|
||||
}
|
||||
|
||||
method("max", function max() {
|
||||
let res = -number.Infinity;
|
||||
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
if (res < arguments[i]) res = arguments[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
});
|
||||
|
||||
method("floor", function floor(val: number) {
|
||||
val = val - 0;
|
||||
if (number.isNaN(val)) return number.NaN;
|
||||
|
||||
let rem = val % 1;
|
||||
if (rem < 0) rem += 1;
|
||||
|
||||
return val - rem;
|
||||
});
|
@ -61,14 +61,14 @@ export const Number = (() => {
|
||||
public static readonly MIN_VALUE: number;
|
||||
}
|
||||
|
||||
object.defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16);
|
||||
object.defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991);
|
||||
object.defineField(Number, "MAX_SAFE_INTEGER", false, false, false, 9007199254740991);
|
||||
object.defineField(Number, "POSITIVE_INFINITY", false, false, false, +number.Infinity);
|
||||
object.defineField(Number, "NEGATIVE_INFINITY", false, false, false, -number.Infinity);
|
||||
object.defineField(Number, "NaN", false, false, false, number.NaN);
|
||||
object.defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308);
|
||||
object.defineField(Number, "MIN_VALUE", false, false, false, 5e-324);
|
||||
object.defineField(Number, "EPSILON", { c: false, e: false, w: false, v: 2.220446049250313e-16 });
|
||||
object.defineField(Number, "MIN_SAFE_INTEGER", { c: false, e: false, w: false, v: -9007199254740991 });
|
||||
object.defineField(Number, "MAX_SAFE_INTEGER", { c: false, e: false, w: false, v: 9007199254740991 });
|
||||
object.defineField(Number, "POSITIVE_INFINITY", { c: false, e: false, w: false, v: +number.Infinity });
|
||||
object.defineField(Number, "NEGATIVE_INFINITY", { c: false, e: false, w: false, v: -number.Infinity });
|
||||
object.defineField(Number, "NaN", { c: false, e: false, w: false, v: number.NaN });
|
||||
object.defineField(Number, "MAX_VALUE", { c: false, e: false, w: false, v: 1.7976931348623157e+308 });
|
||||
object.defineField(Number, "MIN_VALUE", { c: false, e: false, w: false, v: 5e-324 });
|
||||
func.setCallable(Number, true);
|
||||
func.setConstructable(Number, true);
|
||||
|
||||
|
@ -3,8 +3,8 @@ import { TypeError } from "./errors.ts";
|
||||
import { Number } from "./number.ts";
|
||||
import { func, object } from "./primordials.ts";
|
||||
import { String } from "./string.ts";
|
||||
import { symbols, valueKey } from "./utils.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
import { valueKey } from "./utils.ts";
|
||||
|
||||
export const Object = (() => {
|
||||
class Object {
|
||||
@ -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 (Symbol.toStringTag in this) return "[object " + this[Symbol.toStringTag] + "]";
|
||||
if (symbols.toStringTag in this) return "[object " + this[symbols.toStringTag] + "]";
|
||||
else return "[object Object]";
|
||||
}
|
||||
else if (typeof this === "number" || this instanceof Object) return "[object Object]";
|
||||
@ -24,6 +24,9 @@ export const Object = (() => {
|
||||
public valueOf() {
|
||||
return this;
|
||||
}
|
||||
public hasOwnProperty(key: string) {
|
||||
return object.getOwnMember(this, key) != null;
|
||||
}
|
||||
|
||||
public constructor (value?: unknown) {
|
||||
if (typeof value === 'object' && value !== null) return value as any;
|
||||
@ -31,7 +34,7 @@ export const Object = (() => {
|
||||
if (typeof value === 'number') return new Number(value) as any;
|
||||
if (typeof value === 'boolean') return new Boolean(value) as any;
|
||||
if (typeof value === 'symbol') {
|
||||
var res: Symbol = {} as any;
|
||||
const res: Symbol = {} as any;
|
||||
object.setPrototype(res, Symbol.prototype);
|
||||
res[valueKey] = value;
|
||||
return res as any;
|
||||
@ -40,30 +43,49 @@ export const Object = (() => {
|
||||
return {} as any;
|
||||
}
|
||||
|
||||
public static defineProperty(obj: object, key: string | symbol, desc: PropertyDescriptor) {
|
||||
if (obj === null || typeof obj !== "function" && typeof obj !== "object") throw new TypeError("Object.defineProperty called on non-object");
|
||||
if (desc === null || typeof desc !== "function" && typeof desc !== "object") throw new TypeError("Property description must be an object: " + desc);
|
||||
if ("get" in desc || "set" in desc) {
|
||||
var get = desc.get, set = desc.set;
|
||||
public static getOwnPropertyDescriptor(obj: object, key: any) {
|
||||
return object.getOwnMember(obj, key);
|
||||
}
|
||||
|
||||
if (get !== undefined && typeof get !== "function") throw new TypeError("Getter must be a function: " + get);
|
||||
if (set !== undefined && typeof set !== "function") throw new TypeError("Setter must be a function: " + set);
|
||||
if ("value" in desc || "writable" in desc) {
|
||||
throw new TypeError("Invalid property descriptor. Cannot both specify accessors and a value or writable attribute");
|
||||
}
|
||||
if (!object.defineProperty(obj, key, !!desc.enumerable, !!desc.configurable, get, set)) {
|
||||
throw new TypeError("Cannot redefine property: " + String(key));
|
||||
}
|
||||
public static defineProperty(obj: object, key: string | symbol, desc: PropertyDescriptor) {
|
||||
if (obj === null || typeof obj !== "function" && typeof obj !== "object") {
|
||||
throw new TypeError("Object.defineProperty called on non-object");
|
||||
}
|
||||
else if (!object.defineField(obj, key, !!desc.writable, !!desc.enumerable, !!desc.configurable, desc.value)) {
|
||||
throw new TypeError("Cannot redefine property: " + String(key));
|
||||
if (desc === null || typeof desc !== "function" && typeof desc !== "object") {
|
||||
throw new TypeError("Property description must be an object: " + desc);
|
||||
}
|
||||
const res: any = {};
|
||||
|
||||
if ("get" in desc || "set" in desc) {
|
||||
if ("get" in desc) {
|
||||
const get = desc.get;
|
||||
if (get !== undefined && typeof get !== "function") throw new TypeError("Getter must be a function: " + get);
|
||||
res.g = get;
|
||||
}
|
||||
if ("set" in desc) {
|
||||
const set = desc.set;
|
||||
if (set !== undefined && typeof set !== "function") throw new TypeError("Setter must be a function: " + set);
|
||||
res.s = set;
|
||||
}
|
||||
if ("enumerable" in desc) res.e = !!desc.enumerable;
|
||||
if ("configurable" in desc) res.e = !!desc.configurable;
|
||||
|
||||
if (!object.defineProperty(obj, key, res)) throw new TypeError("Cannot redefine property: " + String(key));
|
||||
}
|
||||
else {
|
||||
if ("enumerable" in desc) res.e = !!desc.enumerable;
|
||||
if ("configurable" in desc) res.e = !!desc.configurable;
|
||||
if ("writable" in desc) res.w = !!desc.writable;
|
||||
if ("value" in desc) res.v = desc.value;
|
||||
|
||||
if (!object.defineField(obj, key, res)) throw new TypeError("Cannot redefine property: " + String(key));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
public static defineProperties(obj: object, desc: PropertyDescriptorMap) {
|
||||
const keys = object.getOwnMembers(obj, false);
|
||||
const symbols = object.getOwnSymbolMembers(obj, false);
|
||||
const keys = object.getOwnMembers(desc, false);
|
||||
const symbols = object.getOwnSymbolMembers(desc, false);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
Object.defineProperty(obj, keys[i], desc[keys[i]]);
|
||||
@ -80,8 +102,87 @@ export const Object = (() => {
|
||||
|
||||
return res;
|
||||
}
|
||||
public static assign(target: any) {
|
||||
for (let i = 1; i < arguments.length; i++) {
|
||||
const obj = arguments[i];
|
||||
const keys = object.getOwnMembers(obj, false);
|
||||
const symbols = object.getOwnSymbolMembers(obj, false);
|
||||
|
||||
for (let j = 0; j < keys.length; j++) {
|
||||
target[keys[j]] = obj[keys[j]];
|
||||
}
|
||||
for (let j = 0; j < symbols.length; j++) {
|
||||
target[symbols[j]] = obj[symbols[j]];
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
public static setPrototypeOf(obj: object, proto: object | null) {
|
||||
object.setPrototype(obj, proto!);
|
||||
}
|
||||
public static getPrototypeOf(obj: object) {
|
||||
return object.getPrototype(obj) || null;
|
||||
}
|
||||
|
||||
public static keys(obj: any) {
|
||||
const res: any[] = [];
|
||||
const keys = object.getOwnMembers(obj, false);
|
||||
const symbols = object.getOwnSymbolMembers(obj, false);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
res[res.length] = keys[i];
|
||||
}
|
||||
for (let i = 0; i < symbols.length; i++) {
|
||||
res[res.length] = symbols[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
public static values(obj: any) {
|
||||
const res: any[] = [];
|
||||
const keys = object.getOwnMembers(obj, false);
|
||||
const symbols = object.getOwnSymbolMembers(obj, false);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
res[res.length] = obj[keys[i]];
|
||||
}
|
||||
for (let i = 0; i < symbols.length; i++) {
|
||||
res[res.length] = obj[symbols[i]];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
public static entries(obj: any) {
|
||||
const res: [any, any][] = [];
|
||||
const keys = object.getOwnMembers(obj, false);
|
||||
const symbols = object.getOwnSymbolMembers(obj, false);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
res[res.length] = [keys[i], obj[keys[i]]];
|
||||
}
|
||||
for (let i = 0; i < symbols.length; i++) {
|
||||
res[res.length] = [symbols[i], obj[symbols[i]]];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static preventExtensions(obj: object) {
|
||||
object.preventExt(obj);
|
||||
}
|
||||
public static seal(obj: object) {
|
||||
object.seal(obj);
|
||||
}
|
||||
public static freeze(obj: object) {
|
||||
object.freeze(obj);
|
||||
}
|
||||
}
|
||||
|
||||
object.setPrototype(Object.prototype, undefined);
|
||||
|
||||
func.setCallable(Object, true);
|
||||
func.setConstructable(Object, true);
|
||||
|
||||
|
@ -2,24 +2,25 @@ import { object } from "../primordials.ts";
|
||||
|
||||
function _defineProperties(target, arr) {
|
||||
if (!arr) return;
|
||||
for (var t = 0; t < arr.length; t++) {
|
||||
var desc = arr[t];
|
||||
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var desc = arr[i];
|
||||
var res;
|
||||
|
||||
if ("value" in desc) {
|
||||
object.defineField(target, desc.key, desc.writable || true, desc.enumerable || false, desc.configurable || true, desc.value);
|
||||
res = object.defineField(target, desc.key, { w: desc.writable || true, e: desc.enumerable || true, c: desc.configurable || true, v: desc.value });
|
||||
}
|
||||
else {
|
||||
object.defineProperty(target, desc.key, desc.enumerable || false, desc.configurable || true, desc.get, desc.set);
|
||||
res = object.defineProperty(target, desc.key, { e: desc.enumerable || true, c: desc.configurable || true, g: desc.get, s: desc.set });
|
||||
}
|
||||
|
||||
if (!res) throw "Couldn't set property";
|
||||
}
|
||||
}
|
||||
|
||||
/* __#PURE__ */
|
||||
export default function _createClass(clazz, instance, nonInstance) {
|
||||
if (instance) {
|
||||
_defineProperties(clazz.prototype, instance);
|
||||
_defineProperties(clazz, nonInstance);
|
||||
}
|
||||
_defineProperties(clazz.prototype, instance);
|
||||
_defineProperties(clazz, nonInstance);
|
||||
|
||||
return clazz;
|
||||
}
|
@ -2,6 +2,6 @@ import { object } from "../primordials.ts";
|
||||
|
||||
export default function _defineProperty(obj, key, val) {
|
||||
if (obj == null) return;
|
||||
object.defineField(obj, key, true, true, true, val);
|
||||
object.defineField(obj, key, { c: true, e: true, w: true, v: val });
|
||||
return obj;
|
||||
}
|
||||
|
@ -8,4 +8,4 @@ export default function _inherits(t, e) {
|
||||
object.setPrototype(t.prototype, e.prototype);
|
||||
object.setPrototype(t, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
3
src/lib/libs/polyfills/readOnlyError.js
Normal file
3
src/lib/libs/polyfills/readOnlyError.js
Normal file
@ -0,0 +1,3 @@
|
||||
export default function _readOnlyError(name) {
|
||||
throw name;
|
||||
}
|
@ -15,17 +15,28 @@ export interface StringPrimordials {
|
||||
stringBuild(parts: string[]): string;
|
||||
fromCharCode(char: number): string;
|
||||
fromCodePoint(char: number): string;
|
||||
toCharCode(char: string): number;
|
||||
toCodePoint(char: string, i: number): number;
|
||||
indexOf(str: string, search: string, start: number, reverse?: boolean): number;
|
||||
substring(str: string, start: number, end: number): string;
|
||||
lower(str: string): string;
|
||||
upper(str: string): string;
|
||||
}
|
||||
export interface ObjectPrimordials {
|
||||
defineProperty(obj: object, key: string | number | symbol, enumerable: boolean, configurable: boolean, get?: Function, set?: Function): boolean;
|
||||
defineField(obj: object, key: string | number | symbol, writable: boolean, enumerable: boolean, configurable: boolean, value: any): boolean;
|
||||
getOwnMember(): any;
|
||||
getOwnSymbolMember(): any;
|
||||
defineProperty(obj: object, key: string | number | symbol, conf: { g?: Function, s?: Function, e?: boolean, c?: boolean }): boolean;
|
||||
defineField(obj: object, key: string | number | symbol, conf: { v?: any, e?: boolean, c?: boolean, w?: boolean }): boolean;
|
||||
getOwnMember(obj: object, key: any): PropertyDescriptor | undefined;
|
||||
getOwnMembers(obj: object, onlyEnumerable: boolean): string[];
|
||||
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;
|
||||
|
||||
memcpy(src: any[], dst: any[], srcI: number, dstI: number, n: number): void;
|
||||
}
|
||||
export interface FunctionPrimordials {
|
||||
invokeType(args: IArguments, self: any): "new" | "call";
|
||||
@ -33,8 +44,8 @@ export interface FunctionPrimordials {
|
||||
target(): Function | null | undefined;
|
||||
setConstructable(func: Function, flag: boolean): void;
|
||||
setCallable(func: Function, flag: boolean): void;
|
||||
invoke(func: Function, self: any, args: any[]): void;
|
||||
construct(func: Function, self: any, args: any[]): void;
|
||||
invoke(func: Function, self: any, args: any[]): any;
|
||||
construct(func: Function, self: any, args: any[]): any;
|
||||
}
|
||||
export interface JSONPrimordials {
|
||||
parse(data: string): any;
|
||||
@ -48,20 +59,22 @@ export interface Primordials {
|
||||
object: ObjectPrimordials;
|
||||
function: FunctionPrimordials;
|
||||
json: JSONPrimordials;
|
||||
map: new () => {
|
||||
map: new (weak?: boolean) => {
|
||||
get(key: any): any;
|
||||
has(key: any): boolean;
|
||||
set(key: any, val: any): void;
|
||||
delete(key: any): void;
|
||||
keys(): any[];
|
||||
clear(): void;
|
||||
};
|
||||
regex: new (source: string) => {
|
||||
exec(target: string, offset: number, indices: false): {
|
||||
|
||||
};
|
||||
|
||||
regex: new (source: string, multiline: boolean, noCase: boolean, dotall: boolean, unicode: boolean, unicodeClass: boolean) => {
|
||||
exec(target: string, offset: number, indices: boolean): { matches: RegExpMatchArray, end: number } | null;
|
||||
groupCount(): number;
|
||||
};
|
||||
compile(src: string): Function;
|
||||
setGlobalPrototypes(prototype: Record<string, any>): void;
|
||||
now(): number;
|
||||
}
|
||||
|
||||
globalThis.undefined = void 0;
|
||||
@ -79,4 +92,5 @@ export const {
|
||||
regex,
|
||||
setGlobalPrototypes,
|
||||
compile,
|
||||
now,
|
||||
} = primordials;
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { func, regex } from "./primordials.ts";
|
||||
import { func, regex, symbol } from "./primordials.ts";
|
||||
import { String } from "./string.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
import { ReplaceRange } from "./utils.ts";
|
||||
import { applyReplaces } from "./utils.ts";
|
||||
import { applySplits } from "./utils.ts";
|
||||
import { symbols } from "./utils.ts";
|
||||
|
||||
const regexKey: unique symbol = Symbol("RegExp.impl") as any;
|
||||
const regexKey: unique symbol = symbol.makeSymbol("RegExp.impl") as any;
|
||||
|
||||
export class RegExp {
|
||||
private [regexKey]: InstanceType<typeof regex>;
|
||||
@ -11,11 +14,18 @@ export class RegExp {
|
||||
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 constructor(source: any, flags: string) {
|
||||
source = this.source = String(typeof source === "object" && "source" in source ? source.source : source);
|
||||
flags = String(flags);
|
||||
|
||||
const _regex = this[regexKey] = new regex(source);
|
||||
|
||||
let indices = false;
|
||||
let global = false;
|
||||
@ -49,6 +59,79 @@ export class RegExp {
|
||||
if (unicodeSets) flags += "v";
|
||||
if (sticky) flags += "y";
|
||||
this.flags = flags;
|
||||
this.indices = indices;
|
||||
this.global = global;
|
||||
this.ignoreCase = ignoreCase;
|
||||
this.multiline = multiline;
|
||||
this.dotall = dotall;
|
||||
this.unicode = unicode;
|
||||
this.unicodeSets = unicodeSets;
|
||||
this.sticky = sticky;
|
||||
|
||||
this[regexKey] = new regex(source, multiline, ignoreCase, dotall, unicode, unicodeSets);
|
||||
}
|
||||
|
||||
public exec(target: string) {
|
||||
const useLast = this.global || this.sticky;
|
||||
const start = useLast ? this.lastIndex : 0;
|
||||
|
||||
const match = this[regexKey].exec(target, start, this.indices);
|
||||
if (match != null && !(this.sticky && match.matches.index !== start)) {
|
||||
if (useLast) this.lastIndex = match.end;
|
||||
return match.matches;
|
||||
}
|
||||
|
||||
if (useLast) this.lastIndex = 0;
|
||||
return null;
|
||||
}
|
||||
public test(target: string) {
|
||||
return this.exec(target) != null;
|
||||
}
|
||||
|
||||
public [symbols.split](target: string, limit?: number) {
|
||||
return applySplits(target, limit, offset => {
|
||||
const val = this[regexKey].exec(target, offset, false);
|
||||
if (val == null) return undefined;
|
||||
|
||||
return { start: val.matches.index!, end: val.end };
|
||||
});
|
||||
}
|
||||
public [symbols.replace](target: string, replacer: any) {
|
||||
const matches: ReplaceRange[] = [];
|
||||
const regex = this[regexKey];
|
||||
|
||||
if (this.global) {
|
||||
let offset = 0;
|
||||
|
||||
while (true) {
|
||||
const match = regex.exec(target, offset, false);
|
||||
if (match == null) break;
|
||||
|
||||
const start = match.matches.index;
|
||||
const end = match.end;
|
||||
const arr: string[] = [];
|
||||
for (let i = 0; i < match.matches.length; i++) {
|
||||
arr[i] = match.matches[i];
|
||||
}
|
||||
|
||||
matches[matches.length] = { start: match.matches.index!, end: match.end, matches: arr };
|
||||
|
||||
if (start === end) offset = start + 1;
|
||||
else offset = end;
|
||||
}
|
||||
|
||||
return applyReplaces(target, matches, replacer, regex.groupCount() + 1);
|
||||
}
|
||||
else {
|
||||
const match = this.exec(target);
|
||||
if (match != null) matches[0] = {
|
||||
start: match.index!,
|
||||
end: match.index! + match[0].length,
|
||||
matches: match,
|
||||
}
|
||||
}
|
||||
|
||||
return applyReplaces(target, matches, replacer, regex.groupCount() + 1);
|
||||
}
|
||||
}
|
||||
func.setCallable(RegExp, false);
|
||||
|
117
src/lib/libs/set.ts
Normal file
117
src/lib/libs/set.ts
Normal file
@ -0,0 +1,117 @@
|
||||
import { Array } from "./array.ts";
|
||||
import { func, map, symbol } from "./primordials.ts";
|
||||
import { symbols } from "./utils.ts";
|
||||
|
||||
const mapKey: unique symbol = symbol.makeSymbol("Set.impl") as any;
|
||||
|
||||
export class Set<T> {
|
||||
private [mapKey]: InstanceType<typeof map>;
|
||||
|
||||
public has(key: T): boolean {
|
||||
return this[mapKey].has(key);
|
||||
}
|
||||
public add(val: T) {
|
||||
this[mapKey].set(val, true);
|
||||
return this;
|
||||
}
|
||||
public delete(val: T): boolean {
|
||||
if (!this[mapKey].has(val)) return false;
|
||||
else {
|
||||
this[mapKey].delete(val);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public clear() {
|
||||
this[mapKey].clear();
|
||||
}
|
||||
|
||||
public keys(): T[] {
|
||||
return this[mapKey].keys();
|
||||
}
|
||||
public values(): T[] {
|
||||
return this[mapKey].keys();
|
||||
}
|
||||
public entries(): [T, T][] {
|
||||
const res = this[mapKey].keys();
|
||||
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
res[i] = [res[i], res[i]];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public forEach(cb: Function, self?: any) {
|
||||
const vals = this.values();
|
||||
|
||||
for (let i = 0; i < vals.length; i++) {
|
||||
func.invoke(cb, self, [vals[i], vals[i], this]);
|
||||
}
|
||||
}
|
||||
|
||||
public [symbols.iterator](): Iterator<T> {
|
||||
return func.invoke(Array.prototype[symbols.iterator], this.values(), []) as any;
|
||||
}
|
||||
|
||||
public constructor(iterable?: Iterable<T>) {
|
||||
const _map = this[mapKey] = new map();
|
||||
|
||||
if (iterable != null) {
|
||||
if (Array.isArray(iterable)) {
|
||||
for (let i = 0; i < iterable.length; i++) {
|
||||
if (!(i in iterable)) continue;
|
||||
_map.set(iterable[i], true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const it = (iterable as any)[symbols.iterator]();
|
||||
for (let val = it.next(); !val.done; val = it.next()) {
|
||||
_map.set(val.value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class WeakSet<T> {
|
||||
private [mapKey]: InstanceType<typeof map>;
|
||||
|
||||
public has(key: T): boolean {
|
||||
return this[mapKey].has(key);
|
||||
}
|
||||
public add(val: T) {
|
||||
this[mapKey].set(val, true);
|
||||
return this;
|
||||
}
|
||||
public delete(val: T): boolean {
|
||||
if (!this[mapKey].has(val)) return false;
|
||||
else {
|
||||
this[mapKey].delete(val);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public clear() {
|
||||
this[mapKey].clear();
|
||||
}
|
||||
|
||||
public constructor(iterable?: Iterable<T>) {
|
||||
const _map = this[mapKey] = new map(true);
|
||||
|
||||
if (iterable != null) {
|
||||
if (Array.isArray(iterable)) {
|
||||
for (let i = 0; i < iterable.length; i++) {
|
||||
if (!(i in iterable)) continue;
|
||||
_map.set(iterable[i], true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const it = (iterable as any)[symbols.iterator]();
|
||||
for (let val = it.next(); !val.done; val = it.next()) {
|
||||
_map.set(val.value, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func.setCallable(Set, false);
|
||||
func.setCallable(WeakSet, false);
|
@ -1,6 +1,6 @@
|
||||
import { func, string } from "./primordials.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
import { unwrapThis, valueKey } from "./utils.ts";
|
||||
import { func, number, string } from "./primordials.ts";
|
||||
import { RegExp } from "./regex.ts";
|
||||
import { applyReplaces, applySplits, limitI, ReplaceRange, symbols, unwrapThis, valueKey, wrapI } from "./utils.ts";
|
||||
|
||||
export const String = (() => {
|
||||
class String {
|
||||
@ -17,15 +17,119 @@ export const String = (() => {
|
||||
return unwrapThis(this, "string", String, "String.prototype.valueOf");
|
||||
}
|
||||
|
||||
// public split(val: string) {
|
||||
// const res: string[] = [];
|
||||
public includes(search: string, offset = 0) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.indexOf");
|
||||
return string.indexOf(self, (String as any)(search), +offset, false) >= 0;
|
||||
}
|
||||
|
||||
// while (true) {
|
||||
// val.indexOf();
|
||||
// }
|
||||
// }
|
||||
public indexOf(search: string, offset = 0) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.indexOf");
|
||||
offset = +offset;
|
||||
return string.indexOf(self, search, offset, false);
|
||||
}
|
||||
public lastIndexOf(search: string, offset = 0) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.lastIndexOf");
|
||||
offset = +offset;
|
||||
return string.indexOf(self, search, offset, true);
|
||||
}
|
||||
|
||||
public [Symbol.iterator]() {
|
||||
public charAt(i: number) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.charAt");
|
||||
return self[i];
|
||||
}
|
||||
public charCodeAt(i: number) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.charCodeAt");
|
||||
return self[i] ? string.toCharCode(self[i]) : number.NaN;
|
||||
}
|
||||
public codePointAt(i: number) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.charCodeAt");
|
||||
return i > 0 && i <= self.length ? string.toCodePoint(self, i) : number.NaN;
|
||||
}
|
||||
|
||||
public split(val?: any, limit?: number) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.split");
|
||||
if (val === undefined) return [self];
|
||||
if (val !== null && typeof val === "object" && symbols.split in val) {
|
||||
return val[symbols.split](self, limit);
|
||||
}
|
||||
|
||||
val = (String as any)(val);
|
||||
|
||||
return applySplits(self, limit, offset => {
|
||||
const start = string.indexOf(self, val, offset, false);
|
||||
if (start < 0) return undefined;
|
||||
else return { start, end: start + val.length };
|
||||
});
|
||||
}
|
||||
public replace(val: any, replacer: any) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.replace");
|
||||
if (val !== null && typeof val === "object" && symbols.replace in val) {
|
||||
return val[symbols.replace](self, replacer);
|
||||
}
|
||||
else val = (String as any)(val);
|
||||
|
||||
const i = string.indexOf(self, val, 0);
|
||||
return applyReplaces(self, [{ start: i, end: i + val.length, matches: [val] }], replacer, false);
|
||||
}
|
||||
public replaceAll(val: any, replacer: any) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.replaceAll");
|
||||
if (val !== null && typeof val === "object" && symbols.replace in val) {
|
||||
if (val instanceof RegExp && !val.global) throw new TypeError("replaceAll must be called with a global RegExp");
|
||||
return val[symbols.replace](self, replacer);
|
||||
}
|
||||
else val = (String as any)(val);
|
||||
|
||||
let offset = 0;
|
||||
const matches: ReplaceRange[] = [];
|
||||
const add = val.length === 0 ? 1 : val.length;
|
||||
|
||||
while (true) {
|
||||
const i = string.indexOf(self, val, offset);
|
||||
if (i < 0) break;
|
||||
|
||||
matches[matches.length] = { start: i, end: i + val.length, matches: [val] };
|
||||
if (val.length === 0)
|
||||
offset = i + add;
|
||||
}
|
||||
|
||||
return applyReplaces(self, matches, replacer, false);
|
||||
}
|
||||
|
||||
public slice(this: string, start = 0, end = this.length) {
|
||||
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 <= start) return "";
|
||||
return string.substring(self, start, end);
|
||||
}
|
||||
public substring(this: string, start = 0, end = this.length) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.substring");
|
||||
start = limitI(start, this.length);
|
||||
end = limitI(end, this.length);
|
||||
|
||||
if (end <= start) return "";
|
||||
return string.substring(self, start, end);
|
||||
}
|
||||
public substr(this: string, start = 0, count = this.length - start) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.substr");
|
||||
start = limitI(start, this.length);
|
||||
count = limitI(count, this.length - start);
|
||||
|
||||
if (count <= 0) return "";
|
||||
return string.substring(self, start, count + start);
|
||||
}
|
||||
|
||||
public toLowerCase(this: string) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.toLowerCase");
|
||||
return string.lower(self);
|
||||
}
|
||||
public toUpperCase(this: string) {
|
||||
const self = unwrapThis(this, "string", String, "String.prototype.toLowerCase");
|
||||
return string.upper(self);
|
||||
}
|
||||
|
||||
public [symbols.iterator]() {
|
||||
var i = 0;
|
||||
var arr: string | undefined = unwrapThis(this, "string", String, "String.prototype[Symbol.iterator]");
|
||||
|
||||
@ -42,7 +146,7 @@ export const String = (() => {
|
||||
return { done: false, value: val };
|
||||
}
|
||||
},
|
||||
[Symbol.iterator]() { return this; }
|
||||
[symbols.iterator]() { return this; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { func, object, symbol } from "./primordials.ts";
|
||||
import { unwrapThis, valueKey } from "./utils.ts";
|
||||
import { symbols, unwrapThis, valueKey } from "./utils.ts";
|
||||
|
||||
export const Symbol = (() => {
|
||||
class Symbol {
|
||||
@ -24,29 +24,30 @@ export const Symbol = (() => {
|
||||
return symbol.getSymbol(name + "");
|
||||
}
|
||||
|
||||
public static readonly asyncIterator: unique symbol;
|
||||
public static readonly iterator: unique symbol;
|
||||
public static readonly match: unique symbol;
|
||||
public static readonly matchAll: unique symbol;
|
||||
public static readonly replace: unique symbol;
|
||||
public static readonly search: unique symbol;
|
||||
public static readonly split: unique symbol;
|
||||
public static readonly toStringTag: unique symbol;
|
||||
declare public static readonly asyncIterator: unique symbol;
|
||||
declare public static readonly iterator: unique symbol;
|
||||
declare public static readonly match: unique symbol;
|
||||
declare public static readonly matchAll: unique symbol;
|
||||
declare public static readonly replace: unique symbol;
|
||||
declare public static readonly search: unique symbol;
|
||||
declare public static readonly split: unique symbol;
|
||||
declare public static readonly toStringTag: unique symbol;
|
||||
};
|
||||
|
||||
func.setCallable(Symbol, true);
|
||||
func.setConstructable(Symbol, false);
|
||||
|
||||
object.defineField(Symbol, "asyncIterator", false, false, false, symbol.getSymbol("Symbol.asyncIterator"));
|
||||
object.defineField(Symbol, "iterator", false, false, false, symbol.getSymbol("Symbol.iterator"));
|
||||
object.defineField(Symbol, "match", false, false, false, symbol.getSymbol("Symbol.match"));
|
||||
object.defineField(Symbol, "matchAll", false, false, false, symbol.getSymbol("Symbol.matchAll"));
|
||||
object.defineField(Symbol, "replace", false, false, false, symbol.getSymbol("Symbol.replace"));
|
||||
object.defineField(Symbol, "search", false, false, false, symbol.getSymbol("Symbol.search"));
|
||||
object.defineField(Symbol, "split", false, false, false, symbol.getSymbol("Symbol.split"));
|
||||
object.defineField(Symbol, "toStringTag", false, false, false, symbol.getSymbol("Symbol.toStringTag"));
|
||||
object.defineField(Symbol, "asyncIterator", { c: false, e: false, w: false, v: symbols.asyncIterator });
|
||||
object.defineField(Symbol, "iterator", { c: false, e: false, w: false, v: symbols.iterator });
|
||||
object.defineField(Symbol, "match", { c: false, e: false, w: false, v: symbols.match });
|
||||
object.defineField(Symbol, "matchAll", { c: false, e: false, w: false, v: symbols.matchAll });
|
||||
object.defineField(Symbol, "replace", { c: false, e: false, w: false, v: symbols.replace });
|
||||
object.defineField(Symbol, "search", { c: false, e: false, w: false, v: symbols.search });
|
||||
object.defineField(Symbol, "split", { c: false, e: false, w: false, v: symbols.split });
|
||||
object.defineField(Symbol, "toStringTag", { c: false, e: false, w: false, v: symbols.toStringTag });
|
||||
object.defineField(Symbol, "isConcatSpreadable", { c: false, e: false, w: false, v: symbols.isConcatSpreadable });
|
||||
|
||||
return Symbol as any as typeof Symbol & ((name?: string) => symbol);
|
||||
return Symbol as any as typeof Symbol & ((name?: string) => ReturnType<SymbolConstructor>);
|
||||
})();
|
||||
export type Symbol = InstanceType<typeof Symbol>;
|
||||
|
||||
|
23
src/lib/libs/test.js
Normal file
23
src/lib/libs/test.js
Normal file
@ -0,0 +1,23 @@
|
||||
function split(val, limit) {
|
||||
var self = unwrapThis(this, "string", String, "String.prototype.split");
|
||||
if (val === undefined) return [self];
|
||||
if (val !== null && typeof val === "object" && Symbol.split in val) {
|
||||
return val[Symbol.split](self, limit);
|
||||
}
|
||||
val = String(val);
|
||||
var offset = 0;
|
||||
var res = [];
|
||||
while (true) {
|
||||
var start = string.indexOf(self, val, offset, false);
|
||||
if (start < 0) {
|
||||
res[res.length] = string.substring(self, offset, self.length);
|
||||
break;
|
||||
}
|
||||
var end = start + val.length;
|
||||
res[res.length] = string.substring(self, offset, start);
|
||||
offset = end;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
split(print(), print());
|
@ -1,6 +1,17 @@
|
||||
import { symbol } from "./primordials.ts";
|
||||
import { func, string, symbol } from "./primordials.ts";
|
||||
|
||||
export const valueKey: unique symbol = symbol.makeSymbol("Primitive.value") as any;
|
||||
export namespace symbols {
|
||||
export const asyncIterator: unique symbol = symbol.makeSymbol("Symbol.asyncIterator") as any;
|
||||
export const iterator: unique symbol = symbol.makeSymbol("Symbol.iterator") as any;
|
||||
export const match: unique symbol = symbol.makeSymbol("Symbol.match") as any;
|
||||
export const matchAll: unique symbol = symbol.makeSymbol("Symbol.matchAll") as any;
|
||||
export const replace: unique symbol = symbol.makeSymbol("Symbol.replace") as any;
|
||||
export const search: unique symbol = symbol.makeSymbol("Symbol.search") as any;
|
||||
export const split: unique symbol = symbol.makeSymbol("Symbol.split") as any;
|
||||
export const toStringTag: unique symbol = symbol.makeSymbol("Symbol.toStringTag") as any;
|
||||
export const isConcatSpreadable: unique symbol = symbol.makeSymbol("Symbol.isConcatSpreadable") as any;
|
||||
}
|
||||
|
||||
export interface TypeMap {
|
||||
undefined: undefined;
|
||||
@ -18,4 +29,190 @@ export function unwrapThis<T extends keyof TypeMap>(self: any, type: T, constr:
|
||||
if (typeof self === type) return self;
|
||||
if (defaultVal !== undefined) return defaultVal;
|
||||
throw new TypeError(name + " requires that '" + arg + "' be a " + constr.name);
|
||||
}
|
||||
}
|
||||
export function wrapI(i: number, length: number) {
|
||||
if (i < 0) return (i + length) | 0;
|
||||
else return i | 0;
|
||||
}
|
||||
export function limitI(i: number, max: number) {
|
||||
i |= 0;
|
||||
if (i < 0) return 0;
|
||||
else if (i > max) return max;
|
||||
else return i;
|
||||
}
|
||||
|
||||
export type ReplaceRange = { start: number; end: number; matches: string[]; groups?: Record<string, string>; };
|
||||
type ReplaceLiteral = (string | ((_: { groups: string[]; prev: () => string; next: () => string; }) => string))[];
|
||||
|
||||
function parseReplacer(replacer: string, groupN: number) {
|
||||
const parts: ReplaceLiteral = [];
|
||||
let lastI = 0;
|
||||
let lastSlice = 0;
|
||||
|
||||
while (true) {
|
||||
const i = string.indexOf(replacer, "$", lastI);
|
||||
if (i < 0 || i + 1 >= replacer.length) break;
|
||||
lastI = i + 1;
|
||||
|
||||
switch (replacer[i + 1]) {
|
||||
case "$":
|
||||
parts[parts.length] = string.substring(replacer, lastSlice, i);
|
||||
parts[parts.length] = "$";
|
||||
lastSlice = i + 2;
|
||||
continue;
|
||||
case "&":
|
||||
parts[parts.length] = string.substring(replacer, lastSlice, i);
|
||||
parts[parts.length] = ({ groups }) => groups[0];
|
||||
lastSlice = i + 2;
|
||||
continue;
|
||||
case "`":
|
||||
parts[parts.length] = string.substring(replacer, lastSlice, i);
|
||||
parts[parts.length] = ({ prev }) => prev();
|
||||
lastSlice = i + 2;
|
||||
continue;
|
||||
case "'":
|
||||
parts[parts.length] = string.substring(replacer, lastSlice, i);
|
||||
parts[parts.length] = ({ next }) => next();
|
||||
lastSlice = i + 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
let groupI = 0;
|
||||
let hasGroup = false;
|
||||
let consumedN = 1;
|
||||
|
||||
while (i + consumedN < replacer.length) {
|
||||
const code = string.toCharCode(replacer[i + consumedN]);
|
||||
if (code >= 48 && code <= 57) {
|
||||
const newGroupI = groupI * 10 + code - 48;
|
||||
if (newGroupI < 1 || newGroupI >= groupN) break;
|
||||
|
||||
groupI = newGroupI;
|
||||
hasGroup = true;
|
||||
}
|
||||
consumedN++;
|
||||
}
|
||||
|
||||
if (hasGroup) {
|
||||
parts[parts.length] = string.substring(replacer, lastSlice, i);
|
||||
parts[parts.length] = ({ groups }) => groups[groupI];
|
||||
lastSlice = i + consumedN;
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (lastSlice === 0) return [replacer];
|
||||
else parts[parts.length] = string.substring(replacer, lastSlice, replacer.length);
|
||||
|
||||
return parts;
|
||||
}
|
||||
function executeReplacer(text: string, match: ReplaceRange, literal: ReplaceLiteral, prevEnd?: number, nextStart?: number) {
|
||||
const res = [];
|
||||
|
||||
for (let i = 0; i < literal.length; i++) {
|
||||
const curr = literal[i];
|
||||
if (typeof curr === "function") res[i] = curr({
|
||||
groups: match.matches,
|
||||
next: () => string.substring(text, prevEnd ?? 0, match.start),
|
||||
prev: () => string.substring(text, match.end, nextStart ?? 0),
|
||||
});
|
||||
else res[i] = curr;
|
||||
}
|
||||
|
||||
return string.stringBuild(res);
|
||||
}
|
||||
export function applyReplaces(text: string, ranges: ReplaceRange[], replace: any, groupN?: number | false) {
|
||||
if (ranges.length === 0) return text;
|
||||
|
||||
const res: string[] = [];
|
||||
let offset = 0;
|
||||
|
||||
if (groupN !== false && typeof replace === "string") {
|
||||
if (groupN == null) {
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
const prevEnd = i - 1 >= 0 ? ranges[i - 1].end : undefined;
|
||||
const nextStart = i + 1 < ranges.length ? ranges[i + 1].start : undefined;
|
||||
const range = ranges[i];
|
||||
res[res.length] = string.substring(text, offset, range.start);
|
||||
res[res.length] = executeReplacer(text, range, parseReplacer(replace, range.matches.length), prevEnd, nextStart);
|
||||
offset = range.end;
|
||||
}
|
||||
|
||||
res[res.length] = string.substring(text, offset, text.length);
|
||||
}
|
||||
else {
|
||||
const literal = parseReplacer(replace, groupN);
|
||||
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
const prevEnd = i - 1 >= 0 ? ranges[i - 1].end : undefined;
|
||||
const nextStart = i + 1 < ranges.length ? ranges[i + 1].start : undefined;
|
||||
const range = ranges[i];
|
||||
res[res.length] = string.substring(text, offset, range.start);
|
||||
res[res.length] = executeReplacer(text, range, literal, prevEnd, nextStart);
|
||||
offset = range.end;
|
||||
}
|
||||
|
||||
res[res.length] = string.substring(text, offset, text.length);
|
||||
}
|
||||
return string.stringBuild(res);
|
||||
}
|
||||
|
||||
if (typeof replace === "string") {
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
const range = ranges[i];
|
||||
res[res.length] = string.substring(text, offset, range.start);
|
||||
res[res.length] = replace;
|
||||
offset = range.end;
|
||||
}
|
||||
|
||||
res[res.length] = string.substring(text, offset, text.length);
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < ranges.length; i++) {
|
||||
const range = ranges[i];
|
||||
const args: any[] = range.matches;
|
||||
args[args.length] = range.start;
|
||||
args[args.length] = text;
|
||||
args[args.length] = range.groups;
|
||||
|
||||
res[res.length] = string.substring(text, offset, range.start);
|
||||
res[res.length] = func.invoke(replace, undefined, args);
|
||||
offset = range.end;
|
||||
}
|
||||
|
||||
res[res.length] = string.substring(text, offset, text.length);
|
||||
}
|
||||
|
||||
return string.stringBuild(res);
|
||||
}
|
||||
|
||||
export function applySplits(text: string, limit: number | undefined, next: (offset: number) => { start: number; end: number; } | undefined) {
|
||||
let lastEnd = 0;
|
||||
let lastEmpty = true;
|
||||
let offset = 0;
|
||||
|
||||
const res: string[] = [];
|
||||
|
||||
while (true) {
|
||||
if (limit != null && res.length >= limit) break;
|
||||
|
||||
const curr = next(offset);
|
||||
|
||||
if (curr == null) {
|
||||
if (!lastEmpty) res[res.length] = string.substring(text, lastEnd, text.length);
|
||||
break;
|
||||
}
|
||||
|
||||
const { start, end } = curr;
|
||||
const empty = start === end;
|
||||
|
||||
if (offset > 0 || !empty) res[res.length] = string.substring(text, lastEnd, start);
|
||||
|
||||
lastEnd = end;
|
||||
offset = empty ? end + 1 : end;
|
||||
lastEmpty = empty;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -1,19 +1,28 @@
|
||||
import { createDocumentRegistry, createLanguageService, ModuleKind, ScriptSnapshot, ScriptTarget, type Diagnostic, type CompilerOptions, type IScriptSnapshot, flattenDiagnosticMessageText, CompilerHost } from "typescript";
|
||||
import { createDocumentRegistry, createLanguageService, ModuleKind, ScriptSnapshot, ScriptTarget, type Diagnostic, type CompilerOptions, type IScriptSnapshot, flattenDiagnosticMessageText, CompilerHost, LanguageService } from "typescript";
|
||||
|
||||
declare function getResource(name: string): string;
|
||||
// declare function getResource(name: string): string | undefined;
|
||||
declare function print(...args: any[]): void;
|
||||
declare function register(factory: CompilerFactory): void;
|
||||
// declare function register(factory: CompilerFactory): void;
|
||||
|
||||
type CompilerFactory = (next: Compiler) => Compiler;
|
||||
type Compiler = (filename: string, src: string, maps: any[]) => Function;
|
||||
|
||||
const resources: Record<string, string | undefined> = {};
|
||||
|
||||
function getResource(name: string): string | undefined {
|
||||
if (name === "/lib.d.ts") return "declare var a = 10;";
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function resource(name: string) {
|
||||
if (name in resources) return resources[name];
|
||||
else return resources[name] = getResource(name);
|
||||
}
|
||||
|
||||
function register(factory: CompilerFactory): void {
|
||||
factory((filename, src) => Function(src));
|
||||
}
|
||||
|
||||
register(next => {
|
||||
const files: Record<string, IScriptSnapshot> = {};
|
||||
const versions: Record<string, number> = {};
|
||||
@ -32,34 +41,39 @@ register(next => {
|
||||
declaration: true,
|
||||
};
|
||||
|
||||
const service = createLanguageService({
|
||||
getCurrentDirectory: () => "/",
|
||||
getDefaultLibFileName: () => "/lib.d.ts",
|
||||
getScriptFileNames: () => {
|
||||
const res = ["/src.ts", "/lib.d.ts"];
|
||||
for (let i = 0; i < declI; i++) res.push("/src." + i + ".d.ts");
|
||||
return res;
|
||||
},
|
||||
getCompilationSettings: () => settings,
|
||||
log: print,
|
||||
fileExists: filename => filename in files || resource(filename) != null,
|
||||
|
||||
getScriptSnapshot: (filename) => {
|
||||
if (filename in files) return files[filename];
|
||||
else {
|
||||
const src = resource(filename);
|
||||
if (src == null) return undefined;
|
||||
return files[filename] = ScriptSnapshot.fromString(src);
|
||||
}
|
||||
},
|
||||
getScriptVersion: (filename) => String(versions[filename] || 0),
|
||||
|
||||
readFile: () => { throw "no"; },
|
||||
writeFile: () => { throw "no"; },
|
||||
}, createDocumentRegistry());
|
||||
|
||||
service.getEmitOutput("/lib.d.ts");
|
||||
print("Loaded typescript...");
|
||||
let service: LanguageService;
|
||||
|
||||
measure(() => {
|
||||
service = createLanguageService({
|
||||
getCurrentDirectory: () => "/",
|
||||
getDefaultLibFileName: () => "/lib.d.ts",
|
||||
getScriptFileNames: () => {
|
||||
const res = ["/src.ts", "/lib.d.ts"];
|
||||
for (let i = 0; i < declI; i++) res.push("/src." + i + ".d.ts");
|
||||
return res;
|
||||
},
|
||||
getCompilationSettings: () => settings,
|
||||
log: print,
|
||||
fileExists: filename => filename in files || resource(filename) != null,
|
||||
|
||||
getScriptSnapshot: (filename) => {
|
||||
if (filename in files) return files[filename];
|
||||
else {
|
||||
const src = resource(filename);
|
||||
if (src == null) return undefined;
|
||||
return files[filename] = ScriptSnapshot.fromString(src);
|
||||
}
|
||||
},
|
||||
getScriptVersion: (filename) => String(versions[filename] || 0),
|
||||
|
||||
readFile: () => { throw "no"; },
|
||||
writeFile: () => { throw "no"; },
|
||||
}, createDocumentRegistry());
|
||||
});
|
||||
measure(() => {
|
||||
service.getEmitOutput("/lib.d.ts");
|
||||
});
|
||||
print("Loaded typescript!");
|
||||
|
||||
return (code, filename, mapChain) => {
|
||||
files["/src.ts"] = ScriptSnapshot.fromString(code);
|
||||
|
@ -5,9 +5,13 @@ import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
import me.topchetoeu.jscript.common.Metadata;
|
||||
import me.topchetoeu.jscript.common.Reading;
|
||||
@ -18,8 +22,6 @@ import me.topchetoeu.jscript.common.json.JSON;
|
||||
import me.topchetoeu.jscript.common.parsing.Filename;
|
||||
import me.topchetoeu.jscript.runtime.debug.DebugContext;
|
||||
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
||||
import me.topchetoeu.jscript.runtime.values.Member.PropertyMember;
|
||||
import me.topchetoeu.jscript.runtime.values.Value;
|
||||
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
|
||||
import me.topchetoeu.jscript.runtime.values.functions.NativeFunction;
|
||||
@ -104,82 +106,145 @@ public class SimpleRepl {
|
||||
|
||||
var prototype = new ObjectValue[1];
|
||||
NativeFunction mapConstr = new NativeFunction(args -> {
|
||||
return UserValue.of(new LinkedHashMap<>(), prototype[0]);
|
||||
var isWeak = args.get(0).toBoolean();
|
||||
return UserValue.of(isWeak ? new WeakHashMap<>() : new LinkedHashMap<>(), prototype[0]);
|
||||
});
|
||||
mapConstr.prototype.defineOwnMember(env, "get", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(LinkedHashMap.class);
|
||||
mapConstr.prototype.defineOwnField(env, "get", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(Map.class);
|
||||
var key = getArgs.get(0);
|
||||
var val = map.get(key);
|
||||
return val == null ? Value.UNDEFINED : (Value)val;
|
||||
}));
|
||||
mapConstr.prototype.defineOwnMember(env, "set", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(LinkedHashMap.class);
|
||||
mapConstr.prototype.defineOwnField(env, "set", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(Map.class);
|
||||
var key = getArgs.get(0);
|
||||
var val = getArgs.get(1);
|
||||
map.put(key, val);
|
||||
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
mapConstr.prototype.defineOwnMember(env, "has", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(LinkedHashMap.class);
|
||||
mapConstr.prototype.defineOwnField(env, "has", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(Map.class);
|
||||
var key = getArgs.get(0);
|
||||
return BoolValue.of(map.containsKey(key));
|
||||
}));
|
||||
mapConstr.prototype.defineOwnMember(env, "delete", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(LinkedHashMap.class);
|
||||
mapConstr.prototype.defineOwnField(env, "delete", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(Map.class);
|
||||
var key = getArgs.get(0);
|
||||
map.remove(key);
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
mapConstr.prototype.defineOwnMember(env, "keys", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(LinkedHashMap.class);
|
||||
mapConstr.prototype.defineOwnField(env, "keys", new NativeFunction(getArgs -> {
|
||||
var map = getArgs.self(Map.class);
|
||||
return ArrayValue.of(map.keySet());
|
||||
}));
|
||||
mapConstr.prototype.defineOwnField(env, "clear", new NativeFunction(getArgs -> {
|
||||
getArgs.self(Map.class).clear();
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
prototype[0] = (ObjectValue)mapConstr.prototype;
|
||||
|
||||
return mapConstr;
|
||||
}
|
||||
|
||||
public static String processRegex(String src) {
|
||||
var n = 0;
|
||||
|
||||
var source = new StringBuilder();
|
||||
|
||||
var inBrackets = false;
|
||||
|
||||
while (true) {
|
||||
if (n >= src.length()) break;
|
||||
var c = src.charAt(n++);
|
||||
|
||||
if (c == '\\') {
|
||||
if (n >= src.length()) throw new PatternSyntaxException("Unexpected end", src, n);
|
||||
c = src.charAt(n++);
|
||||
source.append('\\').append(c);
|
||||
}
|
||||
else if (c == '[') {
|
||||
if (inBrackets) source.append("\\[");
|
||||
else {
|
||||
inBrackets = true;
|
||||
source.append('[');
|
||||
}
|
||||
}
|
||||
else if (c == ']') {
|
||||
if (inBrackets) {
|
||||
inBrackets = false;
|
||||
source.append(']');
|
||||
}
|
||||
else throw new PatternSyntaxException("Unexpected ']'", src, n);
|
||||
}
|
||||
else source.append(c);
|
||||
}
|
||||
|
||||
return source.toString();
|
||||
}
|
||||
|
||||
private static ObjectValue regexPrimordials(Environment env) {
|
||||
var res = new ObjectValue();
|
||||
res.setPrototype(null, null);
|
||||
|
||||
var prototype = new ObjectValue[1];
|
||||
NativeFunction mapConstr = new NativeFunction(args -> {
|
||||
var pattern = Pattern.compile(args.get(0).toString(args.env));
|
||||
return UserValue.of(pattern, prototype[0]);
|
||||
var flags = 0;
|
||||
if (args.get(1).toBoolean()) flags |= Pattern.MULTILINE;
|
||||
if (args.get(2).toBoolean()) flags |= Pattern.CASE_INSENSITIVE;
|
||||
if (args.get(3).toBoolean()) flags |= Pattern.DOTALL;
|
||||
if (args.get(4).toBoolean()) flags |= Pattern.UNICODE_CASE | Pattern.CANON_EQ;
|
||||
if (args.get(5).toBoolean()) flags |= Pattern.UNICODE_CHARACTER_CLASS;
|
||||
try {
|
||||
var pattern = Pattern.compile(processRegex(args.get(0).toString(args.env)), flags);
|
||||
return UserValue.of(pattern, prototype[0]);
|
||||
}
|
||||
catch (PatternSyntaxException e) {
|
||||
throw EngineException.ofSyntax("(regex):" + e.getIndex() + ": " + e.getDescription());
|
||||
}
|
||||
});
|
||||
mapConstr.prototype.defineOwnMember(env, "exec", new NativeFunction(args -> {
|
||||
mapConstr.prototype.defineOwnField(env, "exec", new NativeFunction(args -> {
|
||||
var pattern = args.self(Pattern.class);
|
||||
var target = args.get(0).toString(args.env);
|
||||
var offset = args.get(1).toNumber(args.env).getInt();
|
||||
var index = args.get(2).toBoolean();
|
||||
|
||||
var matcher = pattern.matcher(target).region(offset, target.length());
|
||||
if (offset > target.length()) return Value.NULL;
|
||||
|
||||
var obj = new ArrayValue();
|
||||
for (var i = 0; i < matcher.groupCount(); i++) {
|
||||
obj.set(args.env, i, StringValue.of(matcher.group(i)));
|
||||
var matcher = pattern.matcher(target).region(offset, target.length());
|
||||
if (!matcher.find()) return Value.NULL;
|
||||
|
||||
var matchesArr = new ArrayValue(matcher.groupCount() + 1);
|
||||
for (var i = 0; i < matcher.groupCount() + 1; i++) {
|
||||
var group = matcher.group(i);
|
||||
if (group == null) continue;
|
||||
matchesArr.set(args.env, i, StringValue.of(group));
|
||||
}
|
||||
|
||||
obj.defineOwnMember(args.env, "index", NumberValue.of(matcher.start()));
|
||||
obj.defineOwnMember(args.env, "input", StringValue.of(target));
|
||||
matchesArr.defineOwnField(args.env, "index", NumberValue.of(matcher.start()));
|
||||
matchesArr.defineOwnField(args.env, "input", StringValue.of(target));
|
||||
if (index) {
|
||||
var indices = new ArrayValue();
|
||||
indices.setPrototype(args.env, null);
|
||||
for (var i = 0; i < matcher.groupCount(); i++) {
|
||||
obj.set(args.env, i, ArrayValue.of(Arrays.asList(
|
||||
matchesArr.set(args.env, i, ArrayValue.of(Arrays.asList(
|
||||
NumberValue.of(matcher.start(i)),
|
||||
NumberValue.of(matcher.end(i))
|
||||
)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var obj = new ObjectValue();
|
||||
obj.defineOwnField(args.env, "matches", matchesArr);
|
||||
obj.defineOwnField(args.env, "end", NumberValue.of(matcher.end()));
|
||||
|
||||
return Value.UNDEFINED;
|
||||
return obj;
|
||||
// return val == null ? Value.UNDEFINED : (Value)val;
|
||||
}));
|
||||
mapConstr.prototype.defineOwnField(env, "groupCount", new NativeFunction(args -> {
|
||||
var pattern = args.self(Pattern.class);
|
||||
return NumberValue.of(pattern.matcher("").groupCount());
|
||||
}));
|
||||
prototype[0] = (ObjectValue)mapConstr.prototype;
|
||||
|
||||
return mapConstr;
|
||||
@ -189,10 +254,10 @@ public class SimpleRepl {
|
||||
var res = new ObjectValue();
|
||||
res.setPrototype(null, null);
|
||||
|
||||
res.defineOwnMember(env, "makeSymbol", new NativeFunction(args -> new SymbolValue(args.get(0).toString(args.env))));
|
||||
res.defineOwnMember(env, "getSymbol", new NativeFunction(args -> SymbolValue.get(args.get(0).toString(args.env))));
|
||||
res.defineOwnMember(env, "getSymbolKey", new NativeFunction(args -> ((SymbolValue)args.get(0)).key()));
|
||||
res.defineOwnMember(env, "getSymbolDescriptor", new NativeFunction(args -> StringValue.of(((SymbolValue)args.get(0)).value)));
|
||||
res.defineOwnField(env, "makeSymbol", new NativeFunction(args -> new SymbolValue(args.get(0).toString(args.env))));
|
||||
res.defineOwnField(env, "getSymbol", new NativeFunction(args -> SymbolValue.get(args.get(0).toString(args.env))));
|
||||
res.defineOwnField(env, "getSymbolKey", new NativeFunction(args -> ((SymbolValue)args.get(0)).key()));
|
||||
res.defineOwnField(env, "getSymbolDescriptor", new NativeFunction(args -> StringValue.of(((SymbolValue)args.get(0)).value)));
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -201,7 +266,7 @@ public class SimpleRepl {
|
||||
var res = new ObjectValue();
|
||||
res.setPrototype(null, null);
|
||||
|
||||
res.defineOwnMember(env, "parseInt", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "parseInt", new NativeFunction(args -> {
|
||||
var nradix = args.get(1).toNumber(env);
|
||||
var radix = nradix.isInt() ? nradix.getInt() : 10;
|
||||
|
||||
@ -211,15 +276,15 @@ public class SimpleRepl {
|
||||
}
|
||||
else return NumberValue.parseInt(args.get(0).toString(), radix, false);
|
||||
}));
|
||||
res.defineOwnMember(env, "parseFloat", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "parseFloat", new NativeFunction(args -> {
|
||||
if (args.get(0) instanceof NumberValue) {
|
||||
return args.get(0);
|
||||
}
|
||||
else return NumberValue.parseFloat(args.get(0).toString(), false);
|
||||
}));
|
||||
res.defineOwnMember(env, "isNaN", new NativeFunction(args -> BoolValue.of(args.get(0).isNaN())));
|
||||
res.defineOwnMember(env, "NaN", NumberValue.NAN);
|
||||
res.defineOwnMember(env, "Infinity", NumberValue.of(Double.POSITIVE_INFINITY));
|
||||
res.defineOwnField(env, "isNaN", new NativeFunction(args -> BoolValue.of(args.get(0).isNaN())));
|
||||
res.defineOwnField(env, "NaN", NumberValue.NAN);
|
||||
res.defineOwnField(env, "Infinity", NumberValue.of(Double.POSITIVE_INFINITY));
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -228,7 +293,7 @@ public class SimpleRepl {
|
||||
var res = new ObjectValue();
|
||||
res.setPrototype(null, null);
|
||||
|
||||
res.defineOwnMember(env, "stringBuild", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "stringBuild", new NativeFunction(args -> {
|
||||
var parts = ((ArrayValue)args.get(0)).toArray();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
@ -239,15 +304,46 @@ public class SimpleRepl {
|
||||
return StringValue.of(sb.toString());
|
||||
}));
|
||||
|
||||
res.defineOwnMember(env, "fromCharCode", new NativeFunction(args -> {
|
||||
var parts = ((ArrayValue)args.get(0)).toArray();
|
||||
var sb = new StringBuilder();
|
||||
res.defineOwnField(env, "fromCharCode", new NativeFunction(args -> {
|
||||
return StringValue.of(new String(new char[] { (char)args.get(0).toNumber(args.env).getInt() }));
|
||||
}));
|
||||
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
sb.append(((StringValue)parts[i]).value);
|
||||
}
|
||||
res.defineOwnField(env, "toCharCode", new NativeFunction(args -> {
|
||||
return NumberValue.of(args.get(0).toString(args.env).charAt(0));
|
||||
}));
|
||||
res.defineOwnField(env, "toCodePoint", new NativeFunction(args -> {
|
||||
return NumberValue.of(args.get(0).toString(args.env).codePointAt(args.get(1).toNumber(args.env).getInt()));
|
||||
}));
|
||||
|
||||
return StringValue.of(sb.toString());
|
||||
res.defineOwnField(env, "substring", new NativeFunction(args -> {
|
||||
var str = args.get(0).toString(args.env);
|
||||
var start = args.get(1).toNumber(args.env).getInt();
|
||||
var end = args.get(2).toNumber(args.env).getInt();
|
||||
|
||||
if (end <= start) return StringValue.of("");
|
||||
|
||||
start = Math.max(Math.min(start, str.length()), 0);
|
||||
end = Math.max(Math.min(end, str.length()), 0);
|
||||
|
||||
return StringValue.of(str.substring(start, end));
|
||||
}));
|
||||
|
||||
res.defineOwnField(env, "indexOf", new NativeFunction(args -> {
|
||||
var str = args.get(0).toString(args.env);
|
||||
var search = args.get(1).toString(args.env);
|
||||
var start = args.get(2).toNumber(args.env).getInt();
|
||||
if (start > str.length()) return NumberValue.of(-1);
|
||||
var reverse = args.get(3).toBoolean();
|
||||
|
||||
if (reverse) return NumberValue.of(str.lastIndexOf(search, start));
|
||||
else return NumberValue.of(str.indexOf(search, start));
|
||||
}));
|
||||
|
||||
res.defineOwnField(env, "lower", new NativeFunction(args -> {
|
||||
return StringValue.of(args.get(0).toString(args.env).toLowerCase());
|
||||
}));
|
||||
res.defineOwnField(env, "upper", new NativeFunction(args -> {
|
||||
return StringValue.of(args.get(0).toString(args.env).toUpperCase());
|
||||
}));
|
||||
|
||||
return res;
|
||||
@ -257,35 +353,61 @@ public class SimpleRepl {
|
||||
var res = new ObjectValue();
|
||||
res.setPrototype(null, null);
|
||||
|
||||
res.defineOwnMember(env, "defineField", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "defineField", new NativeFunction(args -> {
|
||||
var obj = (ObjectValue)args.get(0);
|
||||
var key = args.get(1);
|
||||
var writable = args.get(2).toBoolean();
|
||||
var enumerable = args.get(3).toBoolean();
|
||||
var configurable = args.get(4).toBoolean();
|
||||
var value = args.get(5);
|
||||
var desc = (ObjectValue)args.get(2);
|
||||
|
||||
return BoolValue.of(obj.defineOwnMember(args.env, key, FieldMember.of(obj, value, configurable, enumerable, writable)));
|
||||
var valField = desc.getOwnMember(env, "v");
|
||||
var writeField = desc.getOwnMember(env, "w");
|
||||
var configField = desc.getOwnMember(env, "c");
|
||||
var enumField = desc.getOwnMember(env, "e");
|
||||
|
||||
var enumerable = enumField == null ? null : enumField.get(env, desc).toBoolean();
|
||||
var configurable = configField == null ? null : configField.get(env, desc).toBoolean();
|
||||
var writable = writeField == null ? null : writeField.get(env, desc).toBoolean();
|
||||
var value = valField == null ? null : valField.get(env, desc);
|
||||
|
||||
return BoolValue.of(obj.defineOwnField(args.env, key, value, configurable, enumerable, writable));
|
||||
}));
|
||||
res.defineOwnMember(env, "defineProperty", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "defineProperty", new NativeFunction(args -> {
|
||||
var obj = (ObjectValue)args.get(0);
|
||||
var key = args.get(1);
|
||||
var enumerable = args.get(2).toBoolean();
|
||||
var configurable = args.get(3).toBoolean();
|
||||
var getter = args.get(4) instanceof VoidValue ? null : (FunctionValue)args.get(4);
|
||||
var setter = args.get(5) instanceof VoidValue ? null : (FunctionValue)args.get(5);
|
||||
var desc = args.get(2);
|
||||
|
||||
return BoolValue.of(obj.defineOwnMember(args.env, key, new PropertyMember(obj, getter, setter, configurable, enumerable)));
|
||||
var configField = desc.getOwnMember(env, "c");
|
||||
var enumField = desc.getOwnMember(env, "e");
|
||||
var getField = desc.getOwnMember(env, "g");
|
||||
var setField = desc.getOwnMember(env, "s");
|
||||
|
||||
var enumerable = enumField == null ? null : enumField.get(env, desc).toBoolean();
|
||||
var configurable = configField == null ? null : configField.get(env, desc).toBoolean();
|
||||
Optional<FunctionValue> getter = null, setter = null;
|
||||
|
||||
if (getField != null) {
|
||||
var getVal = getField.get(env, desc);
|
||||
if (getVal == Value.UNDEFINED) getter = Optional.empty();
|
||||
else getter = Optional.of((FunctionValue)getVal);
|
||||
}
|
||||
if (setField != null) {
|
||||
var setVal = setField.get(env, desc);
|
||||
if (setVal == Value.UNDEFINED) setter = Optional.empty();
|
||||
else setter = Optional.of((FunctionValue)setVal);
|
||||
}
|
||||
|
||||
return BoolValue.of(obj.defineOwnProperty(args.env, key, getter, setter, configurable, enumerable));
|
||||
}));
|
||||
res.defineOwnMember(env, "getPrototype", new NativeFunction(args -> {
|
||||
return args.get(0).getPrototype(env);
|
||||
res.defineOwnField(env, "getPrototype", new NativeFunction(args -> {
|
||||
var proto = args.get(0).getPrototype(env);
|
||||
if (proto == null) return Value.NULL;
|
||||
else return proto;
|
||||
}));
|
||||
res.defineOwnMember(env, "setPrototype", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "setPrototype", new NativeFunction(args -> {
|
||||
var proto = args.get(1) instanceof VoidValue ? null : (ObjectValue)args.get(1);
|
||||
args.get(0).setPrototype(env, proto);
|
||||
return args.get(0);
|
||||
}));
|
||||
res.defineOwnMember(env, "getOwnMembers", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "getOwnMembers", new NativeFunction(args -> {
|
||||
var val = new ArrayValue();
|
||||
|
||||
for (var key : args.get(0).getOwnMembers(env, args.get(1).toBoolean())) {
|
||||
@ -294,12 +416,43 @@ public class SimpleRepl {
|
||||
|
||||
return val;
|
||||
}));
|
||||
res.defineOwnMember(env, "getOwnSymbolMembers", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "getOwnSymbolMembers", new NativeFunction(args -> {
|
||||
return ArrayValue.of(args.get(0).getOwnSymbolMembers(env, args.get(1).toBoolean()));
|
||||
}));
|
||||
res.defineOwnMember(env, "isArray", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "getOwnMember", new NativeFunction(args -> {
|
||||
var obj = args.get(0);
|
||||
var key = args.get(1);
|
||||
|
||||
var member = obj.getOwnMember(args.env, key);
|
||||
if (member == null) return Value.UNDEFINED;
|
||||
else return member.descriptor(args.env, obj);
|
||||
}));
|
||||
res.defineOwnField(env, "isArray", new NativeFunction(args -> {
|
||||
return BoolValue.of(args.get(0) instanceof ArrayValue);
|
||||
}));
|
||||
res.defineOwnField(env, "preventExt", new NativeFunction(args -> {
|
||||
args.get(0).preventExtensions();
|
||||
return VoidValue.UNDEFINED;
|
||||
}));
|
||||
res.defineOwnField(env, "seal", new NativeFunction(args -> {
|
||||
args.get(0).seal();
|
||||
return VoidValue.UNDEFINED;
|
||||
}));
|
||||
res.defineOwnField(env, "freeze", new NativeFunction(args -> {
|
||||
args.get(0).freeze();
|
||||
return VoidValue.UNDEFINED;
|
||||
}));
|
||||
res.defineOwnField(env, "memcpy", new NativeFunction(args -> {
|
||||
var src = (ArrayValue)args.get(0);
|
||||
var dst = (ArrayValue)args.get(1);
|
||||
var srcI = args.get(2).toNumber(args.env).getInt();
|
||||
var dstI = args.get(3).toNumber(args.env).getInt();
|
||||
var n = args.get(4).toNumber(args.env).getInt();
|
||||
|
||||
src.copyTo(dst, srcI, dstI, n);
|
||||
|
||||
return VoidValue.UNDEFINED;
|
||||
}));
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -308,39 +461,39 @@ public class SimpleRepl {
|
||||
var res = new ObjectValue();
|
||||
res.setPrototype(null, null);
|
||||
|
||||
res.defineOwnMember(env, "setCallable", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "setCallable", new NativeFunction(args -> {
|
||||
var func = (FunctionValue)args.get(0);
|
||||
func.enableApply = args.get(1).toBoolean();
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
res.defineOwnMember(env, "setConstructable", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "setConstructable", new NativeFunction(args -> {
|
||||
var func = (FunctionValue)args.get(0);
|
||||
func.enableConstruct = args.get(1).toBoolean();
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
res.defineOwnMember(env, "invokeType", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "invokeType", new NativeFunction(args -> {
|
||||
if (((ArgumentsValue)args.get(0)).frame.isNew) return StringValue.of("new");
|
||||
else return StringValue.of("call");
|
||||
}));
|
||||
res.defineOwnMember(env, "invokeTypeInfer", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "invokeTypeInfer", new NativeFunction(args -> {
|
||||
var frame = Frame.get(args.env, args.get(0).toNumber(args.env).getInt());
|
||||
if (frame.isNew) return StringValue.of("new");
|
||||
else return StringValue.of("call");
|
||||
}));
|
||||
res.defineOwnMember(env, "target", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "target", new NativeFunction(args -> {
|
||||
var frame = Frame.get(args.env, args.get(0).toNumber(args.env).getInt());
|
||||
if (frame.target == null) return Value.UNDEFINED;
|
||||
else return frame.target;
|
||||
}));
|
||||
|
||||
res.defineOwnMember(env, "invoke", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "invoke", new NativeFunction(args -> {
|
||||
var func = (FunctionValue)args.get(0);
|
||||
var self = args.get(1);
|
||||
var funcArgs = (ArrayValue)args.get(2);
|
||||
|
||||
return func.apply(env, self, funcArgs.toArray());
|
||||
}));
|
||||
res.defineOwnMember(env, "construct", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "construct", new NativeFunction(args -> {
|
||||
var func = (FunctionValue)args.get(0);
|
||||
var target = args.get(1);
|
||||
var funcArgs = (ArrayValue)args.get(2);
|
||||
@ -356,10 +509,10 @@ public class SimpleRepl {
|
||||
var res = new ObjectValue();
|
||||
res.setPrototype(null, null);
|
||||
|
||||
res.defineOwnMember(env, "stringify", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "stringify", new NativeFunction(args -> {
|
||||
return StringValue.of(JSON.stringify(JSONConverter.fromJs(env, args.get(0))));
|
||||
}));
|
||||
res.defineOwnMember(env, "parse", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "parse", new NativeFunction(args -> {
|
||||
return JSONConverter.toJs(JSON.parse(null, args.get(0).toString(env)));
|
||||
}));
|
||||
|
||||
@ -377,18 +530,18 @@ public class SimpleRepl {
|
||||
var res = new ObjectValue();
|
||||
res.setPrototype(null, null);
|
||||
|
||||
res.defineOwnMember(env, "symbol", symbolPrimordials(env));
|
||||
res.defineOwnMember(env, "number", numberPrimordials(env));
|
||||
res.defineOwnMember(env, "string", stringPrimordials(env));
|
||||
res.defineOwnMember(env, "object", objectPrimordials(env));
|
||||
res.defineOwnMember(env, "function", functionPrimordials(env));
|
||||
res.defineOwnMember(env, "json", jsonPrimordials(env));
|
||||
res.defineOwnMember(env, "map", mapPrimordials(env));
|
||||
res.defineOwnMember(env, "regex", regexPrimordials(env));
|
||||
res.defineOwnField(env, "symbol", symbolPrimordials(env));
|
||||
res.defineOwnField(env, "number", numberPrimordials(env));
|
||||
res.defineOwnField(env, "string", stringPrimordials(env));
|
||||
res.defineOwnField(env, "object", objectPrimordials(env));
|
||||
res.defineOwnField(env, "function", functionPrimordials(env));
|
||||
res.defineOwnField(env, "json", jsonPrimordials(env));
|
||||
res.defineOwnField(env, "map", mapPrimordials(env));
|
||||
res.defineOwnField(env, "regex", regexPrimordials(env));
|
||||
|
||||
int[] i = new int[1];
|
||||
|
||||
res.defineOwnMember(env, "setGlobalPrototypes", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "setGlobalPrototypes", new NativeFunction(args -> {
|
||||
var obj = (ObjectValue)args.get(0);
|
||||
|
||||
setProto(args.env, env, Value.OBJECT_PROTO, obj, "object");
|
||||
@ -408,7 +561,7 @@ public class SimpleRepl {
|
||||
}
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
res.defineOwnMember(env, "setIntrinsic", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "setIntrinsic", new NativeFunction(args -> {
|
||||
var name = args.get(0).toString(env);
|
||||
var val = args.get(1);
|
||||
|
||||
@ -416,9 +569,12 @@ public class SimpleRepl {
|
||||
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
res.defineOwnMember(env, "compile", new NativeFunction(args -> {
|
||||
res.defineOwnField(env, "compile", new NativeFunction(args -> {
|
||||
return Compiler.compileFunc(env, new Filename("jscript", "func" + i[0]++ + ".js"), args.get(0).toString(env));
|
||||
}));
|
||||
res.defineOwnField(env, "now", new NativeFunction(args -> {
|
||||
return NumberValue.of(System.currentTimeMillis());
|
||||
}));
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -426,8 +582,8 @@ public class SimpleRepl {
|
||||
private static Environment createESEnv() throws InterruptedException, ExecutionException {
|
||||
var env = initEnv();
|
||||
var stubEnv = initEnv();
|
||||
Value.global(stubEnv).defineOwnMember(stubEnv, "target", Value.global(env));
|
||||
Value.global(stubEnv).defineOwnMember(stubEnv, "primordials", primordials(env));
|
||||
Value.global(stubEnv).defineOwnField(stubEnv, "target", Value.global(env));
|
||||
Value.global(stubEnv).defineOwnField(stubEnv, "primordials", primordials(env));
|
||||
|
||||
EventLoop.get(stubEnv).pushMsg(
|
||||
false, stubEnv,
|
||||
@ -443,29 +599,29 @@ public class SimpleRepl {
|
||||
env.add(EventLoop.KEY, engine);
|
||||
env.add(DebugContext.KEY, new DebugContext());
|
||||
env.add(Compiler.KEY, Compiler.DEFAULT);
|
||||
// environment.add(CompileResult.DEBUG_LOG);
|
||||
// env.add(CompileResult.DEBUG_LOG);
|
||||
|
||||
var glob = Value.global(env);
|
||||
|
||||
glob.defineOwnMember(null, "exit", new NativeFunction("exit", args -> {
|
||||
glob.defineOwnField(null, "exit", new NativeFunction("exit", args -> {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new CancellationException();
|
||||
}));
|
||||
glob.defineOwnMember(null, "print", new NativeFunction("print", args -> {
|
||||
glob.defineOwnField(null, "print", new NativeFunction("print", args -> {
|
||||
for (var el : args.args) {
|
||||
if (el instanceof StringValue) System.out.print(((StringValue)el).value);
|
||||
else System.out.print(el.toReadable(args.env));
|
||||
if (el instanceof StringValue) System.out.print(((StringValue)el).value + " \t");
|
||||
else System.out.print(el.toReadable(args.env) + " \t");
|
||||
}
|
||||
System.out.println();
|
||||
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
glob.defineOwnMember(null, "measure", new NativeFunction("measure", args -> {
|
||||
glob.defineOwnField(null, "measure", new NativeFunction("measure", args -> {
|
||||
var start = System.nanoTime();
|
||||
|
||||
((FunctionValue)args.get(0)).apply(args.env, Value.UNDEFINED);
|
||||
|
||||
System.out.println(String.format("Finished in %sns", System.nanoTime() - start));
|
||||
System.out.println(String.format("Finished in %sms", (System.nanoTime() - start) / 1000000.));
|
||||
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user