feat: implement simple env + ts loader
This commit is contained in:
parent
17406c6b81
commit
bed4014bef
56
src/lib/libs/_entry.ts
Normal file
56
src/lib/libs/_entry.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { Boolean } from "./boolean.ts";
|
||||
import { Error, RangeError, SyntaxError, TypeError } from "./errors.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 { RegExp } from "./regex.ts";
|
||||
|
||||
declare global {
|
||||
function print(...args: any[]): void;
|
||||
}
|
||||
|
||||
object.defineField(target, "undefined", false, false, false, undefined);
|
||||
|
||||
target.Symbol = Symbol;
|
||||
target.Number = Number;
|
||||
target.String = String;
|
||||
target.Boolean = Boolean;
|
||||
|
||||
target.Object = Object;
|
||||
target.Function = Function;
|
||||
target.Array = Array;
|
||||
|
||||
target.Error = Error;
|
||||
target.RangeError = RangeError;
|
||||
target.SyntaxError = SyntaxError;
|
||||
target.TypeError = TypeError;
|
||||
|
||||
target.Map = Map;
|
||||
|
||||
target.parseInt = Number.parseInt;
|
||||
target.parseFloat = Number.parseFloat;
|
||||
target.NaN = Number.NaN;
|
||||
target.Infinity = Number.POSITIVE_INFINITY;
|
||||
|
||||
|
||||
target.RegExp = RegExp;
|
||||
|
||||
setGlobalPrototypes({
|
||||
string: String.prototype,
|
||||
number: Number.prototype,
|
||||
boolean: Boolean.prototype,
|
||||
symbol: Symbol.prototype,
|
||||
object: Object.prototype,
|
||||
array: Array.prototype,
|
||||
function: Function.prototype,
|
||||
error: Error.prototype,
|
||||
syntax: SyntaxError.prototype,
|
||||
range: RangeError.prototype,
|
||||
type: TypeError.prototype,
|
||||
regex: RegExp,
|
||||
});
|
53
src/lib/libs/array.ts
Normal file
53
src/lib/libs/array.ts
Normal file
@ -0,0 +1,53 @@
|
||||
import { func, object } from "./primordials.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
|
||||
export const Array = (() => {
|
||||
class Array {
|
||||
public forEach(this: any[], cb: (val: any, i: number, self: this[]) => void, self?: any) {
|
||||
for (let i = 0; i < this.length; i++) {
|
||||
if (i in this) func.invoke(cb, self, [this[i], i, this]);
|
||||
}
|
||||
}
|
||||
|
||||
public [Symbol.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) {
|
||||
arr = undefined;
|
||||
return { done: true, value: undefined };
|
||||
}
|
||||
else {
|
||||
const val = arr[i++];
|
||||
if (i >= arr.length) arr = undefined;
|
||||
return { done: false, value: val };
|
||||
}
|
||||
},
|
||||
[Symbol.iterator]() { return this; }
|
||||
};
|
||||
}
|
||||
|
||||
public constructor (len: unknown) {
|
||||
if (arguments.length === 1 && typeof len === "number") {
|
||||
const res: any[] = [];
|
||||
res.length = len;
|
||||
return res as any;
|
||||
}
|
||||
// TODO: Implement spreading
|
||||
else throw new Error("Spreading not implemented");
|
||||
}
|
||||
|
||||
public static isArray(val: any[]) {
|
||||
object.isArray(val);
|
||||
}
|
||||
}
|
||||
|
||||
func.setCallable(Array, true);
|
||||
func.setConstructable(Array, true);
|
||||
|
||||
return Array as any as typeof Array & ((value?: unknown) => object);
|
||||
})();
|
||||
export type Array = InstanceType<typeof Array>;
|
29
src/lib/libs/boolean.ts
Normal file
29
src/lib/libs/boolean.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { func } from "./primordials.ts";
|
||||
import { unwrapThis, valueKey } from "./utils.ts";
|
||||
|
||||
export const Boolean = (() => {
|
||||
class Boolean {
|
||||
[valueKey]!: boolean;
|
||||
|
||||
public toString() {
|
||||
return "" + unwrapThis(this, "boolean", Boolean, "Boolean.prototype.toString");
|
||||
}
|
||||
public valueOf() {
|
||||
return unwrapThis(this, "boolean", Boolean, "Boolean.prototype.valueOf");
|
||||
}
|
||||
|
||||
public constructor(value?: unknown) {
|
||||
if (func.invokeType(arguments, this) === "call") {
|
||||
if (arguments.length === 0) return false as any;
|
||||
else return !!value as any;
|
||||
}
|
||||
this[valueKey] = (Boolean as any)(value);
|
||||
}
|
||||
};
|
||||
|
||||
func.setCallable(Boolean, true);
|
||||
func.setConstructable(Boolean, true);
|
||||
|
||||
return Boolean as any as typeof Boolean & ((value?: unknown) => symbol);
|
||||
})();
|
||||
export type Boolean = InstanceType<typeof Boolean>;
|
39
src/lib/libs/errors.ts
Normal file
39
src/lib/libs/errors.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { func, object } from "./primordials.ts";
|
||||
import { String } from "./string.ts";
|
||||
|
||||
export class Error {
|
||||
public declare name: string;
|
||||
public declare message: string;
|
||||
|
||||
public toString() {
|
||||
let res = this.name || "Error";
|
||||
const msg = this.message;
|
||||
|
||||
if (msg) res += ": " + msg;
|
||||
return res;
|
||||
}
|
||||
|
||||
public constructor (msg = "") {
|
||||
if (func.invokeType(arguments, this) === "call") return new Error(msg);
|
||||
this.message = String(msg);
|
||||
}
|
||||
}
|
||||
object.defineField(Error.prototype, "name", true, false, true, "Error");
|
||||
object.defineField(Error.prototype, "message", true, false, true, "");
|
||||
func.setCallable(Error, true);
|
||||
func.setConstructable(Error, true);
|
||||
|
||||
export class SyntaxError extends Error { }
|
||||
object.defineField(SyntaxError.prototype, "name", true, false, true, "SyntaxError");
|
||||
func.setCallable(SyntaxError, true);
|
||||
func.setConstructable(SyntaxError, true);
|
||||
|
||||
export class TypeError extends Error { }
|
||||
object.defineField(TypeError.prototype, "name", true, false, true, "TypeError");
|
||||
func.setCallable(TypeError, true);
|
||||
func.setConstructable(TypeError, true);
|
||||
|
||||
export class RangeError extends Error { }
|
||||
object.defineField(RangeError.prototype, "name", true, false, true, "RangeError");
|
||||
func.setCallable(RangeError, true);
|
||||
func.setConstructable(RangeError, true);
|
61
src/lib/libs/function.ts
Normal file
61
src/lib/libs/function.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { compile, func, string } from "./primordials.ts";
|
||||
import { String } from "./string.ts";
|
||||
|
||||
export const Function = (() => {
|
||||
class Function {
|
||||
declare public readonly name: string;
|
||||
declare public readonly length: number;
|
||||
|
||||
public toString(this: Function) {
|
||||
if (this.name !== "") return "function " + this.name + "(...) { ... }";
|
||||
else return "function (...) { ... }";
|
||||
}
|
||||
public valueOf() {
|
||||
return this;
|
||||
}
|
||||
|
||||
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[]) {
|
||||
return func.invoke(this, self, args);
|
||||
}
|
||||
|
||||
public constructor (...args: string[]) {
|
||||
const parts = ["(function anonymous("];
|
||||
for (let i = 0; i < arguments.length - 1; i++) {
|
||||
if (i > 0) parts[parts.length] = ",";
|
||||
parts[parts.length] = arguments[i];
|
||||
}
|
||||
parts[parts.length] = "){\n";
|
||||
parts[parts.length] = String(arguments[arguments.length - 1]);
|
||||
parts[parts.length] = "\n})";
|
||||
var res = compile(string.stringBuild(parts))();
|
||||
return res;
|
||||
}
|
||||
|
||||
public static compile(src = "", { globals = [], wrap = false }: { globals?: string[], wrap?: boolean } = {}) {
|
||||
const parts = [];
|
||||
|
||||
if (wrap) parts[parts.length] = "return (function() {\n";
|
||||
if (globals.length > 0) {
|
||||
parts[parts.length] = "let {";
|
||||
for (let i = 0; i < globals.length; i++) {
|
||||
if (i > 0) parts[parts.length] = ",";
|
||||
parts[parts.length] = globals[i];
|
||||
}
|
||||
parts[parts.length] = "} = arguments[0];";
|
||||
}
|
||||
parts[parts.length] = src;
|
||||
if (wrap) parts[parts.length] = "\n})(arguments[0])";
|
||||
|
||||
const res = compile(string.stringBuild(parts));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
func.setCallable(Function, true);
|
||||
func.setConstructable(Function, true);
|
||||
|
||||
return Function as any as typeof Function & ((value?: unknown) => (...args: any[]) => any);
|
||||
})();
|
61
src/lib/libs/map.ts
Normal file
61
src/lib/libs/map.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { func, map } from "./primordials.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
|
||||
const mapKey: unique symbol = Symbol("Map.impl") as any;
|
||||
|
||||
export class Map<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 keys(): K[] {
|
||||
return this[mapKey].keys();
|
||||
}
|
||||
public values(): V[] {
|
||||
const res = this[mapKey].keys();
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
res[i] = this[mapKey].get(res[i]);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
public entries(): [K, V][] {
|
||||
const res = this[mapKey].keys();
|
||||
for (let i = 0; i < res.length; i++) {
|
||||
res[i] = [res[i], this[mapKey].get(res[i])];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public [Symbol.iterator](): Iterator<[K, V]> {
|
||||
return func.invoke(Array.prototype[Symbol.iterator as any], 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func.setCallable(Map, false);
|
77
src/lib/libs/number.ts
Normal file
77
src/lib/libs/number.ts
Normal file
@ -0,0 +1,77 @@
|
||||
import { func, number, object } from "./primordials.ts";
|
||||
import { unwrapThis, valueKey } from "./utils.ts";
|
||||
|
||||
export const Number = (() => {
|
||||
class Number {
|
||||
[valueKey]!: number;
|
||||
|
||||
public toString() {
|
||||
return "" + unwrapThis(this, "number", Number, "Number.prototype.toString");
|
||||
}
|
||||
public valueOf() {
|
||||
return unwrapThis(this, "number", Number, "Number.prototype.toString");
|
||||
}
|
||||
|
||||
public constructor (value?: unknown) {
|
||||
if (func.invokeType(arguments, this) === "call") {
|
||||
if (arguments.length === 0) return 0 as any;
|
||||
else return +(value as any) as any;
|
||||
}
|
||||
this[valueKey] = (Number as any)(value);
|
||||
}
|
||||
|
||||
public static isFinite(value: number) {
|
||||
value = unwrapThis(value, "number", Number, "Number.isFinite", "value");
|
||||
if (value === undefined || value !== value) return false;
|
||||
if (value === Infinity || value === -Infinity) return false;
|
||||
return true;
|
||||
}
|
||||
public static isInteger(value: number) {
|
||||
value = unwrapThis(value, "number", Number, "Number.isInteger", "value");
|
||||
if (value === undefined) return false;
|
||||
return number.parseInt(value) === value;
|
||||
}
|
||||
public static isNaN(value: number) {
|
||||
return number.isNaN(value);
|
||||
}
|
||||
public static isSafeInteger(value: number) {
|
||||
value = unwrapThis(value, "number", Number, "Number.isSafeInteger", "value");
|
||||
if (value === undefined || number.parseInt(value) !== value) return false;
|
||||
return value >= -9007199254740991 && value <= 9007199254740991;
|
||||
}
|
||||
public static parseFloat(value: unknown) {
|
||||
if (typeof value === "number") return value;
|
||||
else return number.parseFloat(value + "");
|
||||
}
|
||||
public static parseInt(value: unknown, radix = 10) {
|
||||
radix = +radix;
|
||||
if (number.isNaN(radix)) radix = 10;
|
||||
|
||||
if (typeof value === "number") return number.parseInt(value, radix);
|
||||
else return number.parseInt(value + "", radix);
|
||||
}
|
||||
|
||||
public static readonly EPSILON: number;
|
||||
public static readonly MIN_SAFE_INTEGER: number;
|
||||
public static readonly MAX_SAFE_INTEGER: number;
|
||||
public static readonly POSITIVE_INFINITY: number;
|
||||
public static readonly NEGATIVE_INFINITY: number;
|
||||
public static readonly NaN: number;
|
||||
public static readonly MAX_VALUE: number;
|
||||
public static readonly MIN_VALUE: number;
|
||||
}
|
||||
|
||||
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);
|
||||
func.setCallable(Number, true);
|
||||
func.setConstructable(Number, true);
|
||||
|
||||
return Number as any as typeof Number & ((value?: unknown) => number);
|
||||
})();
|
||||
export type Number = InstanceType<typeof Number>;
|
90
src/lib/libs/object.ts
Normal file
90
src/lib/libs/object.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { Boolean } from "./boolean.ts";
|
||||
import { TypeError } from "./errors.ts";
|
||||
import { Number } from "./number.ts";
|
||||
import { func, object } from "./primordials.ts";
|
||||
import { String } from "./string.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
import { valueKey } from "./utils.ts";
|
||||
|
||||
export const Object = (() => {
|
||||
class Object {
|
||||
public toString(this: unknown) {
|
||||
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] + "]";
|
||||
else return "[object Object]";
|
||||
}
|
||||
else if (typeof this === "number" || this instanceof Object) return "[object Object]";
|
||||
else if (typeof this === "symbol" || this instanceof Symbol) return "[object Symbol]";
|
||||
else if (typeof this === "string" || this instanceof String) return "[object String]";
|
||||
else if (typeof this === "boolean" || this instanceof Boolean) return "[object Boolean]";
|
||||
else if (typeof this === "function") return "[object Function]";
|
||||
}
|
||||
public valueOf() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public constructor (value?: unknown) {
|
||||
if (typeof value === 'object' && value !== null) return value as any;
|
||||
if (typeof value === 'string') return new String(value) as any;
|
||||
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;
|
||||
object.setPrototype(res, Symbol.prototype);
|
||||
res[valueKey] = value;
|
||||
return res as any;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
else if (!object.defineField(obj, key, !!desc.writable, !!desc.enumerable, !!desc.configurable, desc.value)) {
|
||||
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);
|
||||
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
Object.defineProperty(obj, keys[i], desc[keys[i]]);
|
||||
}
|
||||
for (let i = 0; i < symbols.length; i++) {
|
||||
Object.defineProperty(obj, symbols[i], desc[symbols[i]]);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
public static create(proto: object, desc?: PropertyDescriptorMap) {
|
||||
let res = object.setPrototype({}, proto);
|
||||
if (desc != null) this.defineProperties(res, desc);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
func.setCallable(Object, true);
|
||||
func.setConstructable(Object, true);
|
||||
|
||||
return Object as any as typeof Object & ((value?: unknown) => object);
|
||||
})();
|
||||
export type Object = InstanceType<typeof Object>;
|
5
src/lib/libs/polyfills/callSuper.js
Normal file
5
src/lib/libs/polyfills/callSuper.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { func, object } from "../primordials.ts";
|
||||
|
||||
export default function _callSuper(self, constr, args) {
|
||||
return func.construct(object.getPrototype(constr), func.target(1), args || []);
|
||||
}
|
5
src/lib/libs/polyfills/classCallCheck.js
Normal file
5
src/lib/libs/polyfills/classCallCheck.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { func } from "../primordials.ts";
|
||||
|
||||
export default function _classCallCheck() {
|
||||
if (func.invokeTypeInfer() !== "new") throw new TypeError("Cannot call a class as a function");
|
||||
}
|
25
src/lib/libs/polyfills/createClass.js
Normal file
25
src/lib/libs/polyfills/createClass.js
Normal file
@ -0,0 +1,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];
|
||||
|
||||
if ("value" in desc) {
|
||||
object.defineField(target, desc.key, desc.writable || true, desc.enumerable || false, desc.configurable || true, desc.value);
|
||||
}
|
||||
else {
|
||||
object.defineProperty(target, desc.key, desc.enumerable || false, desc.configurable || true, desc.get, desc.set);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* __#PURE__ */
|
||||
export default function _createClass(clazz, instance, nonInstance) {
|
||||
if (instance) {
|
||||
_defineProperties(clazz.prototype, instance);
|
||||
_defineProperties(clazz, nonInstance);
|
||||
}
|
||||
|
||||
return clazz;
|
||||
}
|
7
src/lib/libs/polyfills/defineProperty.js
Normal file
7
src/lib/libs/polyfills/defineProperty.js
Normal file
@ -0,0 +1,7 @@
|
||||
import { object } from "../primordials.ts";
|
||||
|
||||
export default function _defineProperty(obj, key, val) {
|
||||
if (obj == null) return;
|
||||
object.defineField(obj, key, true, true, true, val);
|
||||
return obj;
|
||||
}
|
5
src/lib/libs/polyfills/getPrototypeOf.js
Normal file
5
src/lib/libs/polyfills/getPrototypeOf.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { object } from "../primordials.ts";
|
||||
|
||||
export default function _getPrototypeOf(obj) {
|
||||
return object.getPrototype(obj) || null;
|
||||
}
|
11
src/lib/libs/polyfills/inherits.js
Normal file
11
src/lib/libs/polyfills/inherits.js
Normal file
@ -0,0 +1,11 @@
|
||||
import { object } from "../primordials.ts";
|
||||
|
||||
export default function _inherits(t, e) {
|
||||
if (e == null) {
|
||||
object.setPrototype(t.prototype, undefined);
|
||||
}
|
||||
else {
|
||||
object.setPrototype(t.prototype, e.prototype);
|
||||
object.setPrototype(t, e);
|
||||
}
|
||||
}
|
2
src/lib/libs/polyfills/possibleConstructorReturn.js
Normal file
2
src/lib/libs/polyfills/possibleConstructorReturn.js
Normal file
@ -0,0 +1,2 @@
|
||||
export default function _possibleConstructorReturn() {
|
||||
}
|
5
src/lib/libs/polyfills/setPrototypeOf.js
Normal file
5
src/lib/libs/polyfills/setPrototypeOf.js
Normal file
@ -0,0 +1,5 @@
|
||||
import { object } from "../primordials";
|
||||
|
||||
export default function _setPrototypeOf(obj, proto) {
|
||||
object.setPrototype(obj, proto);
|
||||
}
|
3
src/lib/libs/polyfills/typeof.js
Normal file
3
src/lib/libs/polyfills/typeof.js
Normal file
@ -0,0 +1,3 @@
|
||||
export default function _typeof(val) {
|
||||
return typeof val;
|
||||
}
|
82
src/lib/libs/primordials.ts
Normal file
82
src/lib/libs/primordials.ts
Normal file
@ -0,0 +1,82 @@
|
||||
export interface SymbolPrimordials {
|
||||
makeSymbol(name: string): symbol;
|
||||
getSymbol(name: string): symbol;
|
||||
getSymbolKey(symbol: symbol): string | undefined;
|
||||
getSymbolDescription(symbol: symbol): string;
|
||||
}
|
||||
export interface NumberPrimordials {
|
||||
parseInt(raw: string | number, radix?: number): number;
|
||||
parseFloat(raw: string | number): number;
|
||||
isNaN(num: number): boolean;
|
||||
NaN: number;
|
||||
Infinity: number;
|
||||
}
|
||||
export interface StringPrimordials {
|
||||
stringBuild(parts: string[]): string;
|
||||
fromCharCode(char: number): string;
|
||||
fromCodePoint(char: number): 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;
|
||||
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;
|
||||
}
|
||||
export interface FunctionPrimordials {
|
||||
invokeType(args: IArguments, self: any): "new" | "call";
|
||||
invokeTypeInfer(): "new" | "call";
|
||||
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;
|
||||
}
|
||||
export interface JSONPrimordials {
|
||||
parse(data: string): any;
|
||||
stringify(data: any): string;
|
||||
}
|
||||
|
||||
export interface Primordials {
|
||||
symbol: SymbolPrimordials;
|
||||
number: NumberPrimordials;
|
||||
string: StringPrimordials;
|
||||
object: ObjectPrimordials;
|
||||
function: FunctionPrimordials;
|
||||
json: JSONPrimordials;
|
||||
map: new () => {
|
||||
get(key: any): any;
|
||||
has(key: any): boolean;
|
||||
set(key: any, val: any): void;
|
||||
delete(key: any): void;
|
||||
keys(): any[];
|
||||
};
|
||||
regex: new (source: string) => {
|
||||
exec(target: string, offset: number, indices: false): {
|
||||
|
||||
};
|
||||
};
|
||||
compile(src: string): Function;
|
||||
setGlobalPrototypes(prototype: Record<string, any>): void;
|
||||
}
|
||||
|
||||
globalThis.undefined = void 0;
|
||||
export const target = (globalThis as any).target;
|
||||
export const primordials: Primordials = (globalThis as any).primordials;
|
||||
|
||||
export const {
|
||||
symbol,
|
||||
number,
|
||||
string,
|
||||
object,
|
||||
function: func,
|
||||
json,
|
||||
map,
|
||||
regex,
|
||||
setGlobalPrototypes,
|
||||
compile,
|
||||
} = primordials;
|
54
src/lib/libs/regex.ts
Normal file
54
src/lib/libs/regex.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { func, regex } from "./primordials.ts";
|
||||
import { String } from "./string.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
|
||||
const regexKey: unique symbol = Symbol("RegExp.impl") as any;
|
||||
|
||||
export class RegExp {
|
||||
private [regexKey]: InstanceType<typeof regex>;
|
||||
|
||||
public readonly source: string;
|
||||
public readonly flags: string;
|
||||
public lastIndex = 0;
|
||||
|
||||
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;
|
||||
let ignoreCase = false;
|
||||
let multiline = false;
|
||||
let dotall = false;
|
||||
let unicode = false;
|
||||
let unicodeSets = false;
|
||||
let sticky = false;
|
||||
|
||||
for (let i = 0; i < flags.length; i++) {
|
||||
switch (flags[i]) {
|
||||
case "d": indices = true; break;
|
||||
case "g": global = true; break;
|
||||
case "i": ignoreCase = true; break;
|
||||
case "m": multiline = true; break;
|
||||
case "s": dotall = true; break;
|
||||
case "u": unicode = true; break;
|
||||
case "v": unicodeSets = true; break;
|
||||
case "y": sticky = true; break;
|
||||
}
|
||||
}
|
||||
|
||||
flags = "";
|
||||
if (indices) flags += "d";
|
||||
if (global) flags += "g";
|
||||
if (ignoreCase) flags += "i";
|
||||
if (multiline) flags += "m";
|
||||
if (dotall) flags += "s";
|
||||
if (unicode) flags += "u";
|
||||
if (unicodeSets) flags += "v";
|
||||
if (sticky) flags += "y";
|
||||
this.flags = flags;
|
||||
}
|
||||
}
|
||||
func.setCallable(RegExp, false);
|
84
src/lib/libs/string.ts
Normal file
84
src/lib/libs/string.ts
Normal file
@ -0,0 +1,84 @@
|
||||
import { func, string } from "./primordials.ts";
|
||||
import { Symbol } from "./symbol.ts";
|
||||
import { unwrapThis, valueKey } from "./utils.ts";
|
||||
|
||||
export const String = (() => {
|
||||
class String {
|
||||
[valueKey]!: string;
|
||||
|
||||
public at(index: number) {
|
||||
throw "Not implemented :/";
|
||||
return unwrapThis(this, "string", String, "String.prototype.at")[index];
|
||||
};
|
||||
public toString() {
|
||||
return unwrapThis(this, "string", String, "String.prototype.toString");
|
||||
}
|
||||
public valueOf() {
|
||||
return unwrapThis(this, "string", String, "String.prototype.valueOf");
|
||||
}
|
||||
|
||||
// public split(val: string) {
|
||||
// const res: string[] = [];
|
||||
|
||||
// while (true) {
|
||||
// val.indexOf();
|
||||
// }
|
||||
// }
|
||||
|
||||
public [Symbol.iterator]() {
|
||||
var i = 0;
|
||||
var arr: string | undefined = unwrapThis(this, "string", String, "String.prototype[Symbol.iterator]");
|
||||
|
||||
return {
|
||||
next () {
|
||||
if (arr == null) return { done: true, value: undefined };
|
||||
if (i > arr.length) {
|
||||
arr = undefined;
|
||||
return { done: true, value: undefined };
|
||||
}
|
||||
else {
|
||||
var val = arr[i++];
|
||||
if (i >= arr.length) arr = undefined;
|
||||
return { done: false, value: val };
|
||||
}
|
||||
},
|
||||
[Symbol.iterator]() { return this; }
|
||||
};
|
||||
}
|
||||
|
||||
public constructor (value?: unknown) {
|
||||
if (func.invokeType(arguments, this) === "call") {
|
||||
if (arguments.length === 0) return "" as any;
|
||||
else if (typeof value === "symbol") return value.toString() as any;
|
||||
else return (value as any) + "" as any;
|
||||
}
|
||||
this[valueKey] = (String as any)(value);
|
||||
}
|
||||
|
||||
public static fromCharCode(...args: number[]) {
|
||||
const res: string[] = [];
|
||||
res[arguments.length] = "";
|
||||
|
||||
for (let i = 0; i < arguments.length; i++) {
|
||||
res[i] = string.fromCharCode(+arguments[i]);
|
||||
}
|
||||
|
||||
return string.stringBuild(res);
|
||||
}
|
||||
public static fromCodePoint(...args: number[]) {
|
||||
const res: string[] = [];
|
||||
res[arguments.length] = "";
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
res[i] = string.fromCodePoint(+arguments[i]);
|
||||
}
|
||||
return string.stringBuild(res);
|
||||
}
|
||||
}
|
||||
|
||||
func.setCallable(String, true);
|
||||
func.setConstructable(String, true);
|
||||
|
||||
return String as any as typeof String & ((value?: unknown) => string);
|
||||
})();
|
||||
export type String = InstanceType<typeof String>;
|
52
src/lib/libs/symbol.ts
Normal file
52
src/lib/libs/symbol.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { func, object, symbol } from "./primordials.ts";
|
||||
import { unwrapThis, valueKey } from "./utils.ts";
|
||||
|
||||
export const Symbol = (() => {
|
||||
class Symbol {
|
||||
[valueKey]!: symbol;
|
||||
|
||||
get description() {
|
||||
return symbol.getSymbolDescription(unwrapThis(this, "symbol", Symbol, "Symbol.prototype.description"));
|
||||
}
|
||||
|
||||
public toString() {
|
||||
return "Symbol(" + unwrapThis(this, "symbol", Symbol, "Symbol.prototype.toString").description + ")";
|
||||
}
|
||||
public valueOf() {
|
||||
return unwrapThis(this, "symbol", Symbol, "Symbol.prototype.valueOf");
|
||||
}
|
||||
|
||||
public constructor(name = "") {
|
||||
return symbol.makeSymbol(name + "") as any;
|
||||
}
|
||||
|
||||
public static for(name: string) {
|
||||
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;
|
||||
};
|
||||
|
||||
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"));
|
||||
|
||||
return Symbol as any as typeof Symbol & ((name?: string) => symbol);
|
||||
})();
|
||||
export type Symbol = InstanceType<typeof Symbol>;
|
||||
|
21
src/lib/libs/utils.ts
Normal file
21
src/lib/libs/utils.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { symbol } from "./primordials.ts";
|
||||
|
||||
export const valueKey: unique symbol = symbol.makeSymbol("Primitive.value") as any;
|
||||
|
||||
export interface TypeMap {
|
||||
undefined: undefined;
|
||||
boolean: boolean;
|
||||
string: string;
|
||||
number: number;
|
||||
symbol: symbol;
|
||||
object: null | object;
|
||||
function: Function;
|
||||
}
|
||||
|
||||
export function unwrapThis<T extends keyof TypeMap>(self: any, type: T, constr: Function, name: string, arg = "this", defaultVal?: TypeMap[T]): TypeMap[T] {
|
||||
if (typeof self === type) return self;
|
||||
if (self instanceof constr && valueKey in self) self = (self as any)[valueKey];
|
||||
if (typeof self === type) return self;
|
||||
if (defaultVal !== undefined) return defaultVal;
|
||||
throw new TypeError(name + " requires that '" + arg + "' be a " + constr.name);
|
||||
}
|
106
src/lib/ts/_entry.ts
Normal file
106
src/lib/ts/_entry.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import { createDocumentRegistry, createLanguageService, ModuleKind, ScriptSnapshot, ScriptTarget, type Diagnostic, type CompilerOptions, type IScriptSnapshot, flattenDiagnosticMessageText, CompilerHost } from "typescript";
|
||||
|
||||
declare function getResource(name: string): string;
|
||||
declare function print(...args: any[]): 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 resource(name: string) {
|
||||
if (name in resources) return resources[name];
|
||||
else return resources[name] = getResource(name);
|
||||
}
|
||||
|
||||
register(next => {
|
||||
const files: Record<string, IScriptSnapshot> = {};
|
||||
const versions: Record<string, number> = {};
|
||||
let declI = 0;
|
||||
|
||||
const settings: CompilerOptions = {
|
||||
target: ScriptTarget.ESNext,
|
||||
module: ModuleKind.Preserve,
|
||||
|
||||
allowImportingTsExtensions: true,
|
||||
verbatimModuleSyntax: true,
|
||||
|
||||
strict: false,
|
||||
skipLibCheck: true,
|
||||
forceConsistentCasingInFileNames: true,
|
||||
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...");
|
||||
|
||||
return (code, filename, mapChain) => {
|
||||
files["/src.ts"] = ScriptSnapshot.fromString(code);
|
||||
versions["/src.ts"] ??= 0;
|
||||
versions["/src.ts"]++;
|
||||
|
||||
const emit = service.getEmitOutput("/src.ts");
|
||||
|
||||
const diagnostics = new Array<Diagnostic>()
|
||||
.concat(service.getCompilerOptionsDiagnostics())
|
||||
.concat(service.getSyntacticDiagnostics("/src.ts"))
|
||||
.concat(service.getSemanticDiagnostics("/src.ts"))
|
||||
.map(function (diagnostic) {
|
||||
const message = flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
||||
|
||||
if (diagnostic.file != null) {
|
||||
let file = diagnostic.file.fileName.substring(1);
|
||||
if (file === "src.ts") file = filename;
|
||||
|
||||
if (diagnostic.start == null) return file;
|
||||
|
||||
const pos = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
||||
return file + ":" + (pos.line + 1) + ":" + (pos.character + 1) + ": " + message;
|
||||
}
|
||||
else return message;
|
||||
});
|
||||
|
||||
if (diagnostics.length > 0) {
|
||||
throw new SyntaxError(diagnostics.join("\n"));
|
||||
}
|
||||
|
||||
var map = JSON.parse(emit.outputFiles[0].text);
|
||||
var result = emit.outputFiles[1].text;
|
||||
var declaration = emit.outputFiles[2].text;
|
||||
|
||||
var compiled = next(result, filename, mapChain.concat(map));
|
||||
|
||||
return function (this: any) {
|
||||
const res = compiled.apply(this, arguments);
|
||||
if (declaration !== '') files["/src." + declI++ + ".d.ts"] = ScriptSnapshot.fromString(declaration);
|
||||
return res;
|
||||
};
|
||||
};
|
||||
});
|
@ -16,7 +16,6 @@ import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.common.environment.Key;
|
||||
import me.topchetoeu.jscript.common.json.JSON;
|
||||
import me.topchetoeu.jscript.common.parsing.Filename;
|
||||
import me.topchetoeu.jscript.compilation.CompileResult;
|
||||
import me.topchetoeu.jscript.runtime.debug.DebugContext;
|
||||
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
||||
@ -298,6 +297,9 @@ public class SimpleRepl {
|
||||
res.defineOwnMember(env, "getOwnSymbolMembers", new NativeFunction(args -> {
|
||||
return ArrayValue.of(args.get(0).getOwnSymbolMembers(env, args.get(1).toBoolean()));
|
||||
}));
|
||||
res.defineOwnMember(env, "isArray", new NativeFunction(args -> {
|
||||
return BoolValue.of(args.get(0) instanceof ArrayValue);
|
||||
}));
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -320,6 +322,16 @@ public class SimpleRepl {
|
||||
if (((ArgumentsValue)args.get(0)).frame.isNew) return StringValue.of("new");
|
||||
else return StringValue.of("call");
|
||||
}));
|
||||
res.defineOwnMember(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 -> {
|
||||
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 -> {
|
||||
var func = (FunctionValue)args.get(0);
|
||||
@ -330,9 +342,11 @@ public class SimpleRepl {
|
||||
}));
|
||||
res.defineOwnMember(env, "construct", new NativeFunction(args -> {
|
||||
var func = (FunctionValue)args.get(0);
|
||||
var funcArgs = (ArrayValue)args.get(1);
|
||||
var target = args.get(1);
|
||||
var funcArgs = (ArrayValue)args.get(2);
|
||||
|
||||
return func.constructNoSelf(env, funcArgs.toArray());
|
||||
if (target == Value.UNDEFINED) return func.constructNoSelf(env, funcArgs.toArray());
|
||||
else return func.construct(env, target, funcArgs.toArray());
|
||||
}));
|
||||
|
||||
return res;
|
||||
@ -388,9 +402,9 @@ public class SimpleRepl {
|
||||
setProto(args.env, env, Value.SYNTAX_ERR_PROTO, obj, "syntax");
|
||||
setProto(args.env, env, Value.TYPE_ERR_PROTO, obj, "type");
|
||||
setProto(args.env, env, Value.RANGE_ERR_PROTO, obj, "range");
|
||||
var val = obj.getMember(env, "regex");
|
||||
var val = obj.getMember(args.env, "regex");
|
||||
if (val instanceof FunctionValue func) {
|
||||
args.env.add(Value.REGEX_CONSTR, func);
|
||||
env.add(Value.REGEX_CONSTR, func);
|
||||
}
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
@ -409,13 +423,29 @@ public class SimpleRepl {
|
||||
return res;
|
||||
}
|
||||
|
||||
private static void initEnv() {
|
||||
environment.add(EventLoop.KEY, engine);
|
||||
environment.add(DebugContext.KEY, new DebugContext());
|
||||
environment.add(Compiler.KEY, Compiler.DEFAULT);
|
||||
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));
|
||||
|
||||
EventLoop.get(stubEnv).pushMsg(
|
||||
false, stubEnv,
|
||||
Filename.parse("jscript://init.js"), Reading.resourceToString("lib/index.js"),
|
||||
Value.UNDEFINED
|
||||
).get();
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
private static Environment initEnv() {
|
||||
var env = new Environment();
|
||||
env.add(EventLoop.KEY, engine);
|
||||
env.add(DebugContext.KEY, new DebugContext());
|
||||
env.add(Compiler.KEY, Compiler.DEFAULT);
|
||||
// environment.add(CompileResult.DEBUG_LOG);
|
||||
|
||||
var glob = Value.global(environment);
|
||||
var glob = Value.global(env);
|
||||
|
||||
glob.defineOwnMember(null, "exit", new NativeFunction("exit", args -> {
|
||||
Thread.currentThread().interrupt();
|
||||
@ -439,20 +469,26 @@ public class SimpleRepl {
|
||||
|
||||
return Value.UNDEFINED;
|
||||
}));
|
||||
|
||||
return env;
|
||||
}
|
||||
private static void initEngine() {
|
||||
engineTask = engine.start();
|
||||
}
|
||||
private static void initGlobals() throws InterruptedException, ExecutionException {
|
||||
EventLoop.get(environment).pushMsg(
|
||||
false, environment,
|
||||
Filename.parse("jscript://init.js"), Reading.resourceToString("lib/index.js"),
|
||||
Value.UNDEFINED, Value.global(environment), primordials(environment)
|
||||
).get();
|
||||
EventLoop.get(environment).pushMsg(
|
||||
false, environment,
|
||||
Filename.parse("jscript://ts.js"), Reading.resourceToString("lib/ts.js"),
|
||||
Value.UNDEFINED
|
||||
environment = createESEnv();
|
||||
var tsEnv = createESEnv();
|
||||
var res = new FunctionValue[1];
|
||||
var setter = new NativeFunction(args -> {
|
||||
res[0] = (FunctionValue)args.get(0);
|
||||
return Value.UNDEFINED;
|
||||
});
|
||||
|
||||
var ts = Reading.resourceToString("lib/ts.js");
|
||||
if (ts != null) EventLoop.get(tsEnv).pushMsg(
|
||||
false, tsEnv,
|
||||
Filename.parse("jscript://ts.js"), ts,
|
||||
Value.UNDEFINED, setter
|
||||
).get();
|
||||
}
|
||||
|
||||
@ -460,7 +496,7 @@ public class SimpleRepl {
|
||||
SimpleRepl.args = args;
|
||||
var reader = new Thread(SimpleRepl::reader);
|
||||
|
||||
initEnv();
|
||||
environment = initEnv();
|
||||
initEngine();
|
||||
|
||||
reader.setDaemon(true);
|
||||
|
Loading…
Reference in New Issue
Block a user