major changes in preparations for environments

This commit is contained in:
2023-09-04 14:30:57 +03:00
parent d1b37074a6
commit 29d3f378a5
54 changed files with 2512 additions and 2161 deletions

View File

@@ -1,68 +1,64 @@
var env: Environment;
interface Environment {
global: typeof globalThis & Record<string, any>;
proto(name: string): object;
setProto(name: string, val: object): void;
}
interface Internals {
markSpecial(...funcs: Function[]): void;
getEnv(func: Function): Environment | undefined;
setEnv<T>(func: T, env: Environment): T;
apply(func: Function, thisArg: any, args: any[]): any;
delay(timeout: number, callback: Function): () => void;
pushMessage(micro: boolean, func: Function, thisArg: any, args: any[]): void;
// @ts-ignore
return (_env: Environment) => {
env = _env;
env.global.assert = (cond, msg) => {
try {
if (!cond()) throw 'condition not satisfied';
log('Passed ' + msg);
return true;
}
catch (e) {
log('Failed ' + msg + ' because of: ' + e);
return false;
}
}
try {
run('values/object');
run('values/symbol');
run('values/function');
run('values/errors');
run('values/string');
run('values/number');
run('values/boolean');
run('values/array');
strlen(val: string): number;
char(val: string): number;
stringFromStrings(arr: string[]): string;
stringFromChars(arr: number[]): string;
symbol(name?: string): symbol;
symbolToString(sym: symbol): string;
env.internals.special(Object, Function, Error, Array);
isArray(obj: any): boolean;
generator(func: (_yield: <T>(val: T) => unknown) => (...args: any[]) => unknown): GeneratorFunction;
defineField(obj: object, key: any, val: any, writable: boolean, enumerable: boolean, configurable: boolean): boolean;
defineProp(obj: object, key: any, get: Function | undefined, set: Function | undefined, enumerable: boolean, configurable: boolean): boolean;
keys(obj: object, onlyString: boolean): any[];
ownProp(obj: any, key: string): PropertyDescriptor<any, any>;
ownPropKeys(obj: any): any[];
lock(obj: object, type: 'ext' | 'seal' | 'freeze'): void;
extensible(obj: object): boolean;
env.global.setTimeout = (func, delay, ...args) => {
if (typeof func !== 'function') throw new TypeError("func must be a function.");
delay = (delay ?? 0) - 0;
return env.internals.setTimeout(() => func(...args), delay)
};
env.global.setInterval = (func, delay, ...args) => {
if (typeof func !== 'function') throw new TypeError("func must be a function.");
delay = (delay ?? 0) - 0;
return env.internals.setInterval(() => func(...args), delay)
};
env.global.clearTimeout = (id) => {
id = id | 0;
env.internals.clearTimeout(id);
};
env.global.clearInterval = (id) => {
id = id | 0;
env.internals.clearInterval(id);
};
sort(arr: any[], comaprator: (a: any, b: any) => number): void;
}
var env: Environment = arguments[0], internals: Internals = arguments[1];
try {
run('values/object');
run('values/symbol');
run('values/function');
run('values/errors');
run('values/string');
run('values/number');
run('values/boolean');
run('values/array');
run('promise');
run('map');
run('set');
run('regex');
run('timeout');
run('promise');
run('map');
run('set');
run('regex');
run('require');
log('Loaded polyfills!');
log('Loaded polyfills!');
}
catch (e: any) {
let err = 'Uncaught error while loading polyfills: ';
if (typeof Error !== 'undefined' && e instanceof Error && e.toString !== {}.toString) err += e;
else if ('message' in e) {
if ('name' in e) err += e.name + ": " + e.message;
else err += 'Error: ' + e.message;
}
catch (e: any) {
if (!_env.captureErr) throw e;
var err = 'Uncaught error while loading polyfills: ';
if (typeof Error !== 'undefined' && e instanceof Error && e.toString !== {}.toString) err += e;
else if ('message' in e) {
if ('name' in e) err += e.name + ": " + e.message;
else err += 'Error: ' + e.message;
}
else err += e;
log(e);
}
};
else err += e;
log(e);
}

66
lib/lib.d.ts vendored
View File

@@ -46,8 +46,8 @@ type IteratorReturnResult<TReturn> =
type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>;
interface Thenable<T> {
then<NextT>(this: Promise<T>, onFulfilled: PromiseThenFunc<T, NextT>, onRejected?: PromiseRejectFunc): Promise<Awaited<NextT>>;
then(this: Promise<T>, onFulfilled: undefined, onRejected?: PromiseRejectFunc): Promise<T>;
then<NextT>(onFulfilled: PromiseThenFunc<T, NextT>, onRejected?: PromiseRejectFunc): Promise<Awaited<NextT>>;
then(onFulfilled: undefined, onRejected?: PromiseRejectFunc): Promise<T>;
}
interface RegExpResultIndices extends Array<[number, number]> {
@@ -100,7 +100,6 @@ interface IterableIterator<T> extends Iterator<T> {
}
interface AsyncIterator<T, TReturn = any, TNext = undefined> {
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
return?(value?: TReturn | Thenable<TReturn>): Promise<IteratorResult<T, TReturn>>;
throw?(e?: any): Promise<IteratorResult<T, TReturn>>;
@@ -112,65 +111,29 @@ interface AsyncIterableIterator<T> extends AsyncIterator<T> {
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
}
interface Generator<T = unknown, TReturn = any, TNext = unknown> extends Iterator<T, TReturn, TNext> {
interface Generator<T = unknown, TReturn = unknown, TNext = unknown> extends Iterator<T, TReturn, TNext> {
[Symbol.iterator](): Generator<T, TReturn, TNext>;
return(value?: TReturn): IteratorResult<T, TReturn>;
throw(e?: any): IteratorResult<T, TReturn>;
return(value: TReturn): IteratorResult<T, TReturn>;
throw(e: any): IteratorResult<T, TReturn>;
}
interface GeneratorFunction {
/**
* Creates a new Generator object.
* @param args A list of arguments the function accepts.
*/
new (...args: any[]): Generator;
/**
* Creates a new Generator object.
* @param args A list of arguments the function accepts.
*/
(...args: any[]): Generator;
/**
* The length of the arguments.
*/
readonly length: number;
/**
* Returns the name of the function.
*/
readonly name: string;
/**
* A reference to the prototype.
*/
readonly prototype: Generator;
}
interface AsyncGenerator<T = unknown, TReturn = any, TNext = unknown> extends AsyncIterator<T, TReturn, TNext> {
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
interface AsyncGenerator<T = unknown, TReturn = unknown, TNext = unknown> extends AsyncIterator<T, TReturn, TNext> {
return(value: TReturn | Thenable<TReturn>): Promise<IteratorResult<T, TReturn>>;
throw(e: any): Promise<IteratorResult<T, TReturn>>;
[Symbol.asyncIterator](): AsyncGenerator<T, TReturn, TNext>;
}
interface AsyncGeneratorFunction {
/**
* Creates a new AsyncGenerator object.
* @param args A list of arguments the function accepts.
*/
new (...args: any[]): AsyncGenerator;
/**
* Creates a new AsyncGenerator object.
* @param args A list of arguments the function accepts.
*/
(...args: any[]): AsyncGenerator;
/**
* The length of the arguments.
*/
readonly length: number;
/**
* Returns the name of the function.
*/
readonly name: string;
/**
* A reference to the prototype.
*/
readonly prototype: AsyncGenerator;
}
@@ -225,7 +188,6 @@ interface MathObject {
interface Array<T> extends IterableIterator<T> {
[i: number]: T;
constructor: ArrayConstructor;
length: number;
toString(): string;
@@ -283,7 +245,6 @@ interface ArrayConstructor {
interface Boolean {
valueOf(): boolean;
constructor: BooleanConstructor;
}
interface BooleanConstructor {
(val: any): boolean;
@@ -292,10 +253,10 @@ interface BooleanConstructor {
}
interface Error {
constructor: ErrorConstructor;
name: string;
message: string;
stack: string[];
toString(): string;
}
interface ErrorConstructor {
(msg?: any): Error;
@@ -309,7 +270,6 @@ interface TypeErrorConstructor extends ErrorConstructor {
prototype: Error;
}
interface TypeError extends Error {
constructor: TypeErrorConstructor;
name: 'TypeError';
}
@@ -319,7 +279,6 @@ interface RangeErrorConstructor extends ErrorConstructor {
prototype: Error;
}
interface RangeError extends Error {
constructor: RangeErrorConstructor;
name: 'RangeError';
}
@@ -329,7 +288,6 @@ interface SyntaxErrorConstructor extends ErrorConstructor {
prototype: Error;
}
interface SyntaxError extends Error {
constructor: SyntaxErrorConstructor;
name: 'SyntaxError';
}
@@ -341,7 +299,6 @@ interface Function {
toString(): string;
prototype: any;
constructor: FunctionConstructor;
readonly length: number;
name: string;
}
@@ -375,7 +332,6 @@ interface FunctionConstructor extends Function {
interface Number {
toString(): string;
valueOf(): number;
constructor: NumberConstructor;
}
interface NumberConstructor {
(val: any): number;
@@ -477,8 +433,6 @@ interface String {
includes(term: string, start?: number): boolean;
length: number;
constructor: StringConstructor;
}
interface StringConstructor {
(val: any): string;
@@ -491,7 +445,6 @@ interface StringConstructor {
interface Symbol {
valueOf(): symbol;
constructor: SymbolConstructor;
}
interface SymbolConstructor {
(val?: any): symbol;
@@ -511,7 +464,6 @@ interface SymbolConstructor {
}
interface Promise<T> extends Thenable<T> {
constructor: PromiseConstructor;
catch(func: PromiseRejectFunc): Promise<T>;
finally(func: () => void): Promise<T>;
}
@@ -522,7 +474,8 @@ interface PromiseConstructor {
resolve<T>(val: T): Promise<Awaited<T>>;
reject(val: any): Promise<never>;
any<T>(promises: (Promise<T>|T)[]): Promise<T>;
isAwaitable(val: unknown): val is Thenable<any>;
any<T>(promises: T[]): Promise<Awaited<T>>;
race<T>(promises: (Promise<T>|T)[]): Promise<T>;
all<T extends any[]>(promises: T): Promise<{ [Key in keyof T]: Awaited<T[Key]> }>;
allSettled<T extends any[]>(...promises: T): Promise<[...{ [P in keyof T]: PromiseResult<Awaited<T[P]>>}]>;
@@ -544,7 +497,6 @@ declare var parseInt: typeof Number.parseInt;
declare var parseFloat: typeof Number.parseFloat;
declare function log(...vals: any[]): void;
declare function assert(condition: () => unknown, message?: string): boolean;
declare var Array: ArrayConstructor;
declare var Boolean: BooleanConstructor;

View File

@@ -1,29 +1,92 @@
define("map", () => {
var Map = env.global.Map = env.internals.Map;
const syms = { values: internals.symbol('Map.values') } as { readonly values: unique symbol };
Map.prototype[Symbol.iterator] = function() {
return this.entries();
};
class Map<KeyT, ValueT> {
[syms.values]: any = {};
var entries = Map.prototype.entries;
var keys = Map.prototype.keys;
var values = Map.prototype.values;
public [Symbol.iterator](): IterableIterator<[KeyT, ValueT]> {
return this.entries();
}
Map.prototype.entries = function() {
var it = entries.call(this);
it[Symbol.iterator] = () => it;
return it;
};
Map.prototype.keys = function() {
var it = keys.call(this);
it[Symbol.iterator] = () => it;
return it;
};
Map.prototype.values = function() {
var it = values.call(this);
it[Symbol.iterator] = () => it;
return it;
};
public clear() {
this[syms.values] = {};
}
public delete(key: KeyT) {
if ((key as any) in this[syms.values]) {
delete this[syms.values];
return true;
}
else return false;
}
public entries(): IterableIterator<[KeyT, ValueT]> {
const keys = internals.ownPropKeys(this[syms.values]);
let i = 0;
return {
next: () => {
if (i >= keys.length) return { done: true };
else return { done: false, value: [ keys[i], this[syms.values][keys[i++]] ] }
},
[Symbol.iterator]() { return this; }
}
}
public keys(): IterableIterator<KeyT> {
const keys = internals.ownPropKeys(this[syms.values]);
let i = 0;
return {
next: () => {
if (i >= keys.length) return { done: true };
else return { done: false, value: keys[i] }
},
[Symbol.iterator]() { return this; }
}
}
public values(): IterableIterator<ValueT> {
const keys = internals.ownPropKeys(this[syms.values]);
let i = 0;
return {
next: () => {
if (i >= keys.length) return { done: true };
else return { done: false, value: this[syms.values][keys[i++]] }
},
[Symbol.iterator]() { return this; }
}
}
public get(key: KeyT) {
return this[syms.values][key];
}
public set(key: KeyT, val: ValueT) {
this[syms.values][key] = val;
return this;
}
public has(key: KeyT) {
return (key as any) in this[syms.values][key];
}
public get size() {
return internals.ownPropKeys(this[syms.values]).length;
}
public forEach(func: (key: KeyT, val: ValueT, map: Map<KeyT, ValueT>) => void, thisArg?: any) {
const keys = internals.ownPropKeys(this[syms.values]);
for (let i = 0; i < keys.length; i++) {
func(keys[i], this[syms.values][keys[i]], this);
}
}
public constructor(iterable: Iterable<[KeyT, ValueT]>) {
const it = iterable[Symbol.iterator]();
for (let el = it.next(); !el.done; el = it.next()) {
this[syms.values][el.value[0]] = el.value[1];
}
}
}
env.global.Map = Map;
});

View File

@@ -5,7 +5,8 @@ var { define, run } = (() => {
modules[name] = func;
}
function run(name: string) {
return modules[name]();
if (typeof modules[name] === 'function') return modules[name]();
else throw "The module '" + name + "' doesn't exist.";
}
return { define, run };

View File

@@ -1,3 +1,203 @@
define("promise", () => {
(env.global.Promise = env.internals.Promise).prototype[Symbol.typeName] = 'Promise';
const syms = {
callbacks: internals.symbol('Promise.callbacks'),
state: internals.symbol('Promise.state'),
value: internals.symbol('Promise.value'),
handled: internals.symbol('Promise.handled'),
} as {
readonly callbacks: unique symbol,
readonly state: unique symbol,
readonly value: unique symbol,
readonly handled: unique symbol,
}
type Callback<T> = [ PromiseFulfillFunc<T>, PromiseRejectFunc ];
enum State {
Pending,
Fulfilled,
Rejected,
}
function isAwaitable(val: unknown): val is Thenable<any> {
return (
typeof val === 'object' &&
val !== null &&
'then' in val &&
typeof val.then === 'function'
);
}
function resolve(promise: Promise<any>, v: any, state: State) {
if (promise[syms.state] === State.Pending) {
if (typeof v === 'object' && v !== null && 'then' in v && typeof v.then === 'function') {
v.then(
(res: any) => resolve(promise, res, state),
(res: any) => resolve(promise, res, State.Rejected)
);
return;
}
promise[syms.value] = v;
promise[syms.state] = state;
for (let i = 0; i < promise[syms.callbacks]!.length; i++) {
promise[syms.handled] = true;
promise[syms.callbacks]![i][state - 1](v);
}
promise[syms.callbacks] = undefined;
internals.pushMessage(true, internals.setEnv(() => {
if (!promise[syms.handled] && state === State.Rejected) {
log('Uncaught (in promise) ' + promise[syms.value]);
}
}, env), undefined, []);
}
}
class Promise<T> {
public static isAwaitable(val: unknown): val is Thenable<any> {
return isAwaitable(val);
}
public static resolve<T>(val: T): Promise<Awaited<T>> {
return new Promise(res => res(val as any));
}
public static reject<T>(val: T): Promise<Awaited<T>> {
return new Promise((_, rej) => rej(val as any));
}
public static race<T>(vals: T[]): Promise<Awaited<T>> {
if (typeof vals.length !== 'number') throw new TypeError('vals must be an array. Note that Promise.race is not variadic.');
return new Promise((res, rej) => {
for (let i = 0; i < vals.length; i++) {
const val = vals[i];
if (this.isAwaitable(val)) val.then(res, rej);
else res(val as any);
}
});
}
public static any<T>(vals: T[]): Promise<Awaited<T>> {
if (typeof vals.length !== 'number') throw new TypeError('vals must be an array. Note that Promise.any is not variadic.');
return new Promise((res, rej) => {
let n = 0;
for (let i = 0; i < vals.length; i++) {
const val = vals[i];
if (this.isAwaitable(val)) val.then(res, (err) => {
n++;
if (n === vals.length) throw Error('No promise resolved.');
});
else res(val as any);
}
if (vals.length === 0) throw Error('No promise resolved.');
});
}
public static all(vals: any[]): Promise<any[]> {
if (typeof vals.length !== 'number') throw new TypeError('vals must be an array. Note that Promise.all is not variadic.');
return new Promise((res, rej) => {
const result: any[] = [];
let n = 0;
for (let i = 0; i < vals.length; i++) {
const val = vals[i];
if (this.isAwaitable(val)) val.then(
val => {
n++;
result[i] = val;
if (n === vals.length) res(result);
},
rej
);
else {
n++;
result[i] = val;
}
}
if (vals.length === n) res(result);
});
}
public static allSettled(vals: any[]): Promise<any[]> {
if (typeof vals.length !== 'number') throw new TypeError('vals must be an array. Note that Promise.allSettled is not variadic.');
return new Promise((res, rej) => {
const result: any[] = [];
let n = 0;
for (let i = 0; i < vals.length; i++) {
const value = vals[i];
if (this.isAwaitable(value)) value.then(
value => {
n++;
result[i] = { status: 'fulfilled', value };
if (n === vals.length) res(result);
},
reason => {
n++;
result[i] = { status: 'rejected', reason };
if (n === vals.length) res(result);
},
);
else {
n++;
result[i] = { status: 'fulfilled', value };
}
}
if (vals.length === n) res(result);
});
}
[syms.callbacks]?: Callback<T>[] = [];
[syms.handled] = false;
[syms.state] = State.Pending;
[syms.value]?: T | unknown;
public then(onFulfil?: PromiseFulfillFunc<T>, onReject?: PromiseRejectFunc) {
return new Promise((resolve, reject) => {
onFulfil ??= v => v;
onReject ??= v => v;
const callback = (func: (val: any) => any) => (v: any) => {
try { resolve(func(v)); }
catch (e) { reject(e); }
}
switch (this[syms.state]) {
case State.Pending:
this[syms.callbacks]![this[syms.callbacks]!.length] = [callback(onFulfil), callback(onReject)];
break;
case State.Fulfilled:
this[syms.handled] = true;
callback(onFulfil)(this[syms.value]);
break;
case State.Rejected:
this[syms.handled] = true;
callback(onReject)(this[syms.value]);
break;
}
})
}
public catch(func: PromiseRejectFunc) {
return this.then(undefined, func);
}
public finally(func: () => void) {
return this.then(
v => {
func();
return v;
},
v => {
func();
throw v;
}
);
}
public constructor(func: PromiseFunc<T>) {
internals.pushMessage(true, func, undefined, [
((v) => resolve(this, v, State.Fulfilled)) as PromiseFulfillFunc<T>,
((err) => resolve(this, err, State.Rejected)) as PromiseRejectFunc
]);
}
}
env.global.Promise = Promise as any;
});

View File

@@ -1,143 +1,143 @@
define("regex", () => {
var RegExp = env.global.RegExp = env.internals.RegExp;
// var RegExp = env.global.RegExp = env.internals.RegExp;
setProps(RegExp.prototype as RegExp, env, {
[Symbol.typeName]: 'RegExp',
// setProps(RegExp.prototype as RegExp, env, {
// [Symbol.typeName]: 'RegExp',
test(val) {
return !!this.exec(val);
},
toString() {
return '/' + this.source + '/' + this.flags;
},
// test(val) {
// return !!this.exec(val);
// },
// toString() {
// return '/' + this.source + '/' + this.flags;
// },
[Symbol.match](target) {
if (this.global) {
const res: string[] = [];
let val;
while (val = this.exec(target)) {
res.push(val[0]);
}
this.lastIndex = 0;
return res;
}
else {
const res = this.exec(target);
if (!this.sticky) this.lastIndex = 0;
return res;
}
},
[Symbol.matchAll](target) {
let pattern: RegExp | undefined = new this.constructor(this, this.flags + "g") as RegExp;
// [Symbol.match](target) {
// if (this.global) {
// const res: string[] = [];
// let val;
// while (val = this.exec(target)) {
// res.push(val[0]);
// }
// this.lastIndex = 0;
// return res;
// }
// else {
// const res = this.exec(target);
// if (!this.sticky) this.lastIndex = 0;
// return res;
// }
// },
// [Symbol.matchAll](target) {
// let pattern: RegExp | undefined = new this.constructor(this, this.flags + "g") as RegExp;
return {
next: (): IteratorResult<RegExpResult, undefined> => {
const val = pattern?.exec(target);
// return {
// next: (): IteratorResult<RegExpResult, undefined> => {
// const val = pattern?.exec(target);
if (val === null || val === undefined) {
pattern = undefined;
return { done: true };
}
else return { value: val };
},
[Symbol.iterator]() { return this; }
}
},
[Symbol.split](target, limit, sensible) {
const pattern = new this.constructor(this, this.flags + "g") as RegExp;
let match: RegExpResult | null;
let lastEnd = 0;
const res: string[] = [];
// if (val === null || val === undefined) {
// pattern = undefined;
// return { done: true };
// }
// else return { value: val };
// },
// [Symbol.iterator]() { return this; }
// }
// },
// [Symbol.split](target, limit, sensible) {
// const pattern = new this.constructor(this, this.flags + "g") as RegExp;
// let match: RegExpResult | null;
// let lastEnd = 0;
// const res: string[] = [];
while ((match = pattern.exec(target)) !== null) {
let added: string[] = [];
// while ((match = pattern.exec(target)) !== null) {
// let added: string[] = [];
if (match.index >= target.length) break;
// if (match.index >= target.length) break;
if (match[0].length === 0) {
added = [ target.substring(lastEnd, pattern.lastIndex), ];
if (pattern.lastIndex < target.length) added.push(...match.slice(1));
}
else if (match.index - lastEnd > 0) {
added = [ target.substring(lastEnd, match.index), ...match.slice(1) ];
}
else {
for (let i = 1; i < match.length; i++) {
res[res.length - match.length + i] = match[i];
}
}
// if (match[0].length === 0) {
// added = [ target.substring(lastEnd, pattern.lastIndex), ];
// if (pattern.lastIndex < target.length) added.push(...match.slice(1));
// }
// else if (match.index - lastEnd > 0) {
// added = [ target.substring(lastEnd, match.index), ...match.slice(1) ];
// }
// else {
// for (let i = 1; i < match.length; i++) {
// res[res.length - match.length + i] = match[i];
// }
// }
if (sensible) {
if (limit !== undefined && res.length + added.length >= limit) break;
else res.push(...added);
}
else {
for (let i = 0; i < added.length; i++) {
if (limit !== undefined && res.length >= limit) return res;
else res.push(added[i]);
}
}
// if (sensible) {
// if (limit !== undefined && res.length + added.length >= limit) break;
// else res.push(...added);
// }
// else {
// for (let i = 0; i < added.length; i++) {
// if (limit !== undefined && res.length >= limit) return res;
// else res.push(added[i]);
// }
// }
lastEnd = pattern.lastIndex;
}
// lastEnd = pattern.lastIndex;
// }
if (lastEnd < target.length) {
res.push(target.substring(lastEnd));
}
// if (lastEnd < target.length) {
// res.push(target.substring(lastEnd));
// }
return res;
},
[Symbol.replace](target, replacement) {
const pattern = new this.constructor(this, this.flags + "d") as RegExp;
let match: RegExpResult | null;
let lastEnd = 0;
const res: string[] = [];
// return res;
// },
// [Symbol.replace](target, replacement) {
// const pattern = new this.constructor(this, this.flags + "d") as RegExp;
// let match: RegExpResult | null;
// let lastEnd = 0;
// const res: string[] = [];
// log(pattern.toString());
// // log(pattern.toString());
while ((match = pattern.exec(target)) !== null) {
const indices = match.indices![0];
res.push(target.substring(lastEnd, indices[0]));
if (replacement instanceof Function) {
res.push(replacement(target.substring(indices[0], indices[1]), ...match.slice(1), indices[0], target));
}
else {
res.push(replacement);
}
lastEnd = indices[1];
if (!pattern.global) break;
}
// while ((match = pattern.exec(target)) !== null) {
// const indices = match.indices![0];
// res.push(target.substring(lastEnd, indices[0]));
// if (replacement instanceof Function) {
// res.push(replacement(target.substring(indices[0], indices[1]), ...match.slice(1), indices[0], target));
// }
// else {
// res.push(replacement);
// }
// lastEnd = indices[1];
// if (!pattern.global) break;
// }
if (lastEnd < target.length) {
res.push(target.substring(lastEnd));
}
// if (lastEnd < target.length) {
// res.push(target.substring(lastEnd));
// }
return res.join('');
},
[Symbol.search](target, reverse, start) {
const pattern: RegExp | undefined = new this.constructor(this, this.flags + "g") as RegExp;
// return res.join('');
// },
// [Symbol.search](target, reverse, start) {
// const pattern: RegExp | undefined = new this.constructor(this, this.flags + "g") as RegExp;
if (!reverse) {
pattern.lastIndex = (start as any) | 0;
const res = pattern.exec(target);
if (res) return res.index;
else return -1;
}
else {
start ??= target.length;
start |= 0;
let res: RegExpResult | null = null;
// if (!reverse) {
// pattern.lastIndex = (start as any) | 0;
// const res = pattern.exec(target);
// if (res) return res.index;
// else return -1;
// }
// else {
// start ??= target.length;
// start |= 0;
// let res: RegExpResult | null = null;
while (true) {
const tmp = pattern.exec(target);
if (tmp === null || tmp.index > start) break;
res = tmp;
}
// while (true) {
// const tmp = pattern.exec(target);
// if (tmp === null || tmp.index > start) break;
// res = tmp;
// }
if (res && res.index <= start) return res.index;
else return -1;
}
},
});
// if (res && res.index <= start) return res.index;
// else return -1;
// }
// },
// });
});

View File

@@ -1,26 +1,80 @@
define("set", () => {
var Set = env.global.Set = env.internals.Set;
Set.prototype[Symbol.iterator] = function() {
return this.values();
};
const syms = { values: internals.symbol('Map.values') } as { readonly values: unique symbol };
var entries = Set.prototype.entries;
var keys = Set.prototype.keys;
var values = Set.prototype.values;
class Set<T> {
[syms.values]: any = {};
Set.prototype.entries = function() {
var it = entries.call(this);
it[Symbol.iterator] = () => it;
return it;
};
Set.prototype.keys = function() {
var it = keys.call(this);
it[Symbol.iterator] = () => it;
return it;
};
Set.prototype.values = function() {
var it = values.call(this);
it[Symbol.iterator] = () => it;
return it;
};
public [Symbol.iterator](): IterableIterator<[T, T]> {
return this.entries();
}
public clear() {
this[syms.values] = {};
}
public delete(key: T) {
if ((key as any) in this[syms.values]) {
delete this[syms.values];
return true;
}
else return false;
}
public entries(): IterableIterator<[T, T]> {
const keys = internals.ownPropKeys(this[syms.values]);
let i = 0;
return {
next: () => {
if (i >= keys.length) return { done: true };
else return { done: false, value: [ keys[i], keys[i] ] }
},
[Symbol.iterator]() { return this; }
}
}
public keys(): IterableIterator<T> {
const keys = internals.ownPropKeys(this[syms.values]);
let i = 0;
return {
next: () => {
if (i >= keys.length) return { done: true };
else return { done: false, value: keys[i] }
},
[Symbol.iterator]() { return this; }
}
}
public values(): IterableIterator<T> {
return this.keys();
}
public add(val: T) {
this[syms.values][val] = undefined;
return this;
}
public has(key: T) {
return (key as any) in this[syms.values][key];
}
public get size() {
return internals.ownPropKeys(this[syms.values]).length;
}
public forEach(func: (key: T, val: T, map: Set<T>) => void, thisArg?: any) {
const keys = internals.ownPropKeys(this[syms.values]);
for (let i = 0; i < keys.length; i++) {
func(keys[i], this[syms.values][keys[i]], this);
}
}
public constructor(iterable: Iterable<T>) {
const it = iterable[Symbol.iterator]();
for (let el = it.next(); !el.done; el = it.next()) {
this[syms.values][el.value] = undefined;
}
}
}
env.global.Set = Set;
});

38
lib/timeout.ts Normal file
View File

@@ -0,0 +1,38 @@
define("timeout", () => {
const timeouts: Record<number, () => void> = { };
const intervals: Record<number, () => void> = { };
let timeoutI = 0, intervalI = 0;
env.global.setTimeout = (func, delay, ...args) => {
if (typeof func !== 'function') throw new TypeError("func must be a function.");
delay = (delay ?? 0) - 0;
const cancelFunc = internals.delay(delay, () => internals.apply(func, undefined, args));
timeouts[++timeoutI] = cancelFunc;
return timeoutI;
};
env.global.setInterval = (func, delay, ...args) => {
if (typeof func !== 'function') throw new TypeError("func must be a function.");
delay = (delay ?? 0) - 0;
const i = ++intervalI;
intervals[i] = internals.delay(delay, callback);
return i;
function callback() {
internals.apply(func, undefined, args);
intervals[i] = internals.delay(delay!, callback);
}
};
env.global.clearTimeout = (id) => {
const func = timeouts[id];
if (func) func();
timeouts[id] = undefined!;
};
env.global.clearInterval = (id) => {
const func = intervals[id];
if (func) func();
intervals[id] = undefined!;
};
});

View File

@@ -15,6 +15,7 @@
"map.ts",
"set.ts",
"regex.ts",
"timeout.ts",
"core.ts"
],
"compilerOptions": {

View File

@@ -1,9 +1,3 @@
interface Environment {
global: typeof globalThis & Record<string, any>;
captureErr: boolean;
internals: any;
}
function setProps<
TargetT extends object,
DescT extends {
@@ -11,11 +5,11 @@ function setProps<
((this: TargetT, ...args: ArgsT) => RetT) :
TargetT[x]
}
>(target: TargetT, env: Environment, desc: DescT) {
var props = env.internals.keys(desc, false);
>(target: TargetT, desc: DescT) {
var props = internals.keys(desc, false);
for (var i = 0; i < props.length; i++) {
var key = props[i];
env.internals.defineField(
internals.defineField(
target, key, (desc as any)[key],
true, // writable
false, // enumerable
@@ -23,8 +17,8 @@ function setProps<
);
}
}
function setConstr<ConstrT, T extends { constructor: ConstrT }>(target: T, constr: ConstrT, env: Environment) {
env.internals.defineField(
function setConstr(target: object, constr: Function) {
internals.defineField(
target, 'constructor', constr,
true, // writable
false, // enumerable

View File

@@ -11,20 +11,20 @@ define("values/array", () => {
res[i] = arguments[i];
}
}
return res;
} as ArrayConstructor;
Array.prototype = ([] as any).__proto__ as Array<any>;
setConstr(Array.prototype, Array, env);
env.setProto('array', Array.prototype);
(Array.prototype as any)[Symbol.typeName] = "Array";
setProps(Array.prototype, env, {
setConstr(Array.prototype, Array);
setProps(Array.prototype, {
[Symbol.iterator]: function() {
return this.values();
},
[Symbol.typeName]: "Array",
values() {
var i = 0;
@@ -67,7 +67,7 @@ define("values/array", () => {
concat() {
var res = [] as any[];
res.push.apply(res, this);
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (arg instanceof Array) {
@@ -296,7 +296,7 @@ define("values/array", () => {
if (typeof func !== 'function') throw new TypeError('Expected func to be undefined or a function.');
env.internals.sort(this, func);
internals.sort(this, func);
return this;
},
splice(start, deleteCount, ...items) {
@@ -328,8 +328,9 @@ define("values/array", () => {
return res;
}
});
setProps(Array, env, {
isArray(val: any) { return env.internals.isArr(val); }
setProps(Array, {
isArray(val: any) { return internals.isArray(val); }
});
internals.markSpecial(Array);
});

View File

@@ -7,6 +7,6 @@ define("values/boolean", () => {
else (this as any).value = val;
} as BooleanConstructor;
Boolean.prototype = (false as any).__proto__ as Boolean;
setConstr(Boolean.prototype, Boolean, env);
env.setProto('bool', Boolean.prototype);
setConstr(Boolean.prototype, Boolean);
});

View File

@@ -8,36 +8,39 @@ define("values/errors", () => {
stack: [] as string[],
}, Error.prototype);
} as ErrorConstructor;
Error.prototype = env.internals.err ?? {};
Error.prototype.name = 'Error';
setConstr(Error.prototype, Error, env);
Error.prototype.toString = function() {
if (!(this instanceof Error)) return '';
if (this.message === '') return this.name;
else return this.name + ': ' + this.message;
};
setConstr(Error.prototype, Error);
setProps(Error.prototype, {
name: 'Error',
toString: internals.setEnv(function(this: Error) {
if (!(this instanceof Error)) return '';
if (this.message === '') return this.name;
else return this.name + ': ' + this.message;
}, env)
});
env.setProto('error', Error.prototype);
internals.markSpecial(Error);
function makeError<T extends ErrorConstructor>(name: string, proto: any): T {
var err = function (msg: string) {
function makeError<T1 extends ErrorConstructor>(name: string, proto: string): T1 {
function constr (msg: string) {
var res = new Error(msg);
(res as any).__proto__ = err.prototype;
(res as any).__proto__ = constr.prototype;
return res;
} as T;
}
err.prototype = proto;
err.prototype.name = name;
setConstr(err.prototype, err as ErrorConstructor, env);
(err.prototype as any).__proto__ = Error.prototype;
(err as any).__proto__ = Error;
env.internals.special(err);
(constr as any).__proto__ = Error;
(constr.prototype as any).__proto__ = env.proto('error');
setConstr(constr.prototype, constr as ErrorConstructor);
setProps(constr.prototype, { name: name });
return err;
internals.markSpecial(constr);
env.setProto(proto, constr.prototype);
return constr as T1;
}
env.global.RangeError = makeError('RangeError', env.internals.range ?? {});
env.global.TypeError = makeError('TypeError', env.internals.type ?? {});
env.global.SyntaxError = makeError('SyntaxError', env.internals.syntax ?? {});
env.global.RangeError = makeError('RangeError', 'rangeErr');
env.global.TypeError = makeError('TypeError', 'typeErr');
env.global.SyntaxError = makeError('SyntaxError', 'syntaxErr');
});

View File

@@ -3,15 +3,15 @@ define("values/function", () => {
throw 'Using the constructor Function() is forbidden.';
} as unknown as FunctionConstructor;
Function.prototype = (Function as any).__proto__ as Function;
setConstr(Function.prototype, Function, env);
env.setProto('function', Function.prototype);
setConstr(Function.prototype, Function);
setProps(Function.prototype, env, {
setProps(Function.prototype, {
apply(thisArg, args) {
if (typeof args !== 'object') throw 'Expected arguments to be an array-like object.';
var len = args.length - 0;
let newArgs: any[];
if (Array.isArray(args)) newArgs = args;
if (internals.isArray(args)) newArgs = args;
else {
newArgs = [];
@@ -21,21 +21,20 @@ define("values/function", () => {
}
}
return env.internals.apply(this, thisArg, newArgs);
return internals.apply(this, thisArg, newArgs);
},
call(thisArg, ...args) {
return this.apply(thisArg, args);
},
bind(thisArg, ...args) {
var func = this;
const func = this;
const res = function() {
const resArgs = [];
var res = function() {
var resArgs = [];
for (var i = 0; i < args.length; i++) {
for (let i = 0; i < args.length; i++) {
resArgs[i] = args[i];
}
for (var i = 0; i < arguments.length; i++) {
for (let i = 0; i < arguments.length; i++) {
resArgs[i + args.length] = arguments[i];
}
@@ -48,7 +47,7 @@ define("values/function", () => {
return 'function (...) { ... }';
},
});
setProps(Function, env, {
setProps(Function, {
async(func) {
if (typeof func !== 'function') throw new TypeError('Expected func to be function.');
@@ -56,7 +55,7 @@ define("values/function", () => {
const args = arguments;
return new Promise((res, rej) => {
const gen = Function.generator(func as any).apply(this, args as any);
const gen = internals.apply(internals.generator(func as any), this, args as any);
(function next(type: 'none' | 'err' | 'ret', val?: any) {
try {
@@ -83,11 +82,11 @@ define("values/function", () => {
asyncGenerator(func) {
if (typeof func !== 'function') throw new TypeError('Expected func to be function.');
return function(this: any) {
const gen = Function.generator<any[], ['await' | 'yield', any]>((_yield) => func(
return function(this: any, ...args: any[]) {
const gen = internals.apply(internals.generator((_yield) => func(
val => _yield(['await', val]) as any,
val => _yield(['yield', val])
)).apply(this, arguments as any);
)), this, args) as Generator<['await' | 'yield', any]>;
const next = (resolve: Function, reject: Function, type: 'none' | 'val' | 'ret' | 'err', val?: any) => {
let res;
@@ -124,17 +123,18 @@ define("values/function", () => {
},
generator(func) {
if (typeof func !== 'function') throw new TypeError('Expected func to be function.');
const gen = env.internals.makeGenerator(func);
return (...args: any[]) => {
const it = gen(args);
const gen = internals.generator(func);
return function(this: any, ...args: any[]) {
const it = internals.apply(gen, this, args);
return {
next: it.next,
return: it.return,
throw: it.throw,
next: (...args) => internals.apply(it.next, it, args),
return: (val) => internals.apply(it.next, it, [val]),
throw: (val) => internals.apply(it.next, it, [val]),
[Symbol.iterator]() { return this; }
}
}
}
})
internals.markSpecial(Function);
});

View File

@@ -7,10 +7,10 @@ define("values/number", () => {
else (this as any).value = val;
} as NumberConstructor;
Number.prototype = (0 as any).__proto__ as Number;
setConstr(Number.prototype, Number, env);
env.setProto('number', Number.prototype);
setConstr(Number.prototype, Number);
setProps(Number.prototype, env, {
setProps(Number.prototype, {
valueOf() {
if (typeof this === 'number') return this;
else return (this as any).value;
@@ -21,13 +21,13 @@ define("values/number", () => {
}
});
setProps(Number, env, {
parseInt(val) { return Math.trunc(Number.parseFloat(val)); },
parseFloat(val) { return env.internals.parseFloat(val); },
setProps(Number, {
parseInt(val) { return Math.trunc(val as any - 0); },
parseFloat(val) { return val as any - 0; },
});
env.global.Object.defineProperty(env.global, 'parseInt', { value: Number.parseInt, writable: false });
env.global.Object.defineProperty(env.global, 'parseFloat', { value: Number.parseFloat, writable: false });
env.global.parseInt = Number.parseInt;
env.global.parseFloat = Number.parseFloat;
env.global.Object.defineProperty(env.global, 'NaN', { value: 0 / 0, writable: false });
env.global.Object.defineProperty(env.global, 'Infinity', { value: 1 / 0, writable: false });
});

View File

@@ -8,8 +8,9 @@ define("values/object", () => {
return arg;
} as ObjectConstructor;
Object.prototype = ({} as any).__proto__ as Object;
setConstr(Object.prototype, Object as any, env);
env.setProto('object', Object.prototype);
(Object.prototype as any).__proto__ = null;
setConstr(Object.prototype, Object as any);
function throwNotObject(obj: any, name: string) {
if (obj === null || typeof obj !== 'object' && typeof obj !== 'function') {
@@ -20,8 +21,8 @@ define("values/object", () => {
return typeof obj === 'object' && obj !== null || typeof obj === 'function';
}
setProps(Object, env, {
assign: function(dst, ...src) {
setProps(Object, {
assign(dst, ...src) {
throwNotObject(dst, 'assign');
for (let i = 0; i < src.length; i++) {
const obj = src[i];
@@ -40,10 +41,10 @@ define("values/object", () => {
defineProperty(obj, key, attrib) {
throwNotObject(obj, 'defineProperty');
if (typeof attrib !== 'object') throw new TypeError('Expected attributes to be an object.');
if ('value' in attrib) {
if ('get' in attrib || 'set' in attrib) throw new TypeError('Cannot specify a value and accessors for a property.');
if (!env.internals.defineField(
if (!internals.defineField(
obj, key,
attrib.value,
!!attrib.writable,
@@ -54,8 +55,8 @@ define("values/object", () => {
else {
if (typeof attrib.get !== 'function' && attrib.get !== undefined) throw new TypeError('Get accessor must be a function.');
if (typeof attrib.set !== 'function' && attrib.set !== undefined) throw new TypeError('Set accessor must be a function.');
if (!env.internals.defineProp(
if (!internals.defineProp(
obj, key,
attrib.get,
attrib.set,
@@ -63,50 +64,87 @@ define("values/object", () => {
!!attrib.configurable
)) throw new TypeError('Can\'t define property \'' + key + '\'.');
}
return obj;
},
defineProperties(obj, attrib) {
throwNotObject(obj, 'defineProperties');
if (typeof attrib !== 'object' && typeof attrib !== 'function') throw 'Expected second argument to be an object.';
for (var key in attrib) {
Object.defineProperty(obj, key, attrib[key]);
}
return obj;
},
keys(obj, onlyString) {
onlyString = !!(onlyString ?? true);
return env.internals.keys(obj, onlyString);
return internals.keys(obj, !!(onlyString ?? true));
},
entries(obj, onlyString) {
return Object.keys(obj, onlyString).map(v => [ v, (obj as any)[v] ]);
const res = [];
const keys = internals.keys(obj, !!(onlyString ?? true));
for (let i = 0; i < keys.length; i++) {
res[i] = [ keys[i], (obj as any)[keys[i]] ];
}
return keys;
},
values(obj, onlyString) {
return Object.keys(obj, onlyString).map(v => (obj as any)[v]);
const res = [];
const keys = internals.keys(obj, !!(onlyString ?? true));
for (let i = 0; i < keys.length; i++) {
res[i] = (obj as any)[keys[i]];
}
return keys;
},
getOwnPropertyDescriptor(obj, key) {
return env.internals.ownProp(obj, key);
return internals.ownProp(obj, key) as any;
},
getOwnPropertyDescriptors(obj) {
return Object.fromEntries([
...Object.getOwnPropertyNames(obj),
...Object.getOwnPropertySymbols(obj)
].map(v => [ v, Object.getOwnPropertyDescriptor(obj, v) ])) as any;
const res = [];
const keys = internals.ownPropKeys(obj);
for (let i = 0; i < keys.length; i++) {
res[i] = internals.ownProp(obj, keys[i]);
}
return res;
},
getOwnPropertyNames(obj) {
return env.internals.ownPropKeys(obj, false);
const arr = internals.ownPropKeys(obj);
const res = [];
for (let i = 0; i < arr.length; i++) {
if (typeof arr[i] === 'symbol') continue;
res[res.length] = arr[i];
}
return res as any;
},
getOwnPropertySymbols(obj) {
return env.internals.ownPropKeys(obj, true);
const arr = internals.ownPropKeys(obj);
const res = [];
for (let i = 0; i < arr.length; i++) {
if (typeof arr[i] !== 'symbol') continue;
res[res.length] = arr[i];
}
return res as any;
},
hasOwn(obj, key) {
if (Object.getOwnPropertyNames(obj).includes(key)) return true;
if (Object.getOwnPropertySymbols(obj).includes(key)) return true;
const keys = internals.ownPropKeys(obj);
for (let i = 0; i < keys.length; i++) {
if (keys[i] === key) return true;
}
return false;
},
@@ -130,41 +168,51 @@ define("values/object", () => {
preventExtensions(obj) {
throwNotObject(obj, 'preventExtensions');
env.internals.preventExtensions(obj);
internals.lock(obj, 'ext');
return obj;
},
seal(obj) {
throwNotObject(obj, 'seal');
env.internals.seal(obj);
internals.lock(obj, 'seal');
return obj;
},
freeze(obj) {
throwNotObject(obj, 'freeze');
env.internals.freeze(obj);
internals.lock(obj, 'freeze');
return obj;
},
isExtensible(obj) {
if (!check(obj)) return false;
return env.internals.extensible(obj);
return internals.extensible(obj);
},
isSealed(obj) {
if (!check(obj)) return true;
if (Object.isExtensible(obj)) return false;
return Object.getOwnPropertyNames(obj).every(v => !Object.getOwnPropertyDescriptor(obj, v).configurable);
if (internals.extensible(obj)) return false;
const keys = internals.ownPropKeys(obj);
for (let i = 0; i < keys.length; i++) {
if (internals.ownProp(obj, keys[i]).configurable) return false;
}
return true;
},
isFrozen(obj) {
if (!check(obj)) return true;
if (Object.isExtensible(obj)) return false;
return Object.getOwnPropertyNames(obj).every(v => {
var prop = Object.getOwnPropertyDescriptor(obj, v);
if (internals.extensible(obj)) return false;
const keys = internals.ownPropKeys(obj);
for (let i = 0; i < keys.length; i++) {
const prop = internals.ownProp(obj, keys[i]);
if (prop.configurable) return false;
if ('writable' in prop && prop.writable) return false;
return !prop.configurable;
});
}
return true;
}
});
setProps(Object.prototype, env, {
setProps(Object.prototype, {
valueOf() {
return this;
},
@@ -175,4 +223,5 @@ define("values/object", () => {
return Object.hasOwn(this, key);
},
});
internals.markSpecial(Object);
});

View File

@@ -7,10 +7,10 @@ define("values/string", () => {
else (this as any).value = val;
} as StringConstructor;
String.prototype = ('' as any).__proto__ as String;
setConstr(String.prototype, String, env);
env.setProto('string', String.prototype);
setConstr(String.prototype, String);
setProps(String.prototype, env, {
setProps(String.prototype, {
toString() {
if (typeof this === 'string') return this;
else return (this as any).value;
@@ -27,7 +27,14 @@ define("values/string", () => {
}
start = start ?? 0 | 0;
end = (end ?? this.length) | 0;
return env.internals.substring(this, start, end);
const res = [];
for (let i = start; i < end; i++) {
if (i >= 0 && i < this.length) res[res.length] = this[i];
}
return internals.stringFromStrings(res);
},
substr(start, length) {
start = start ?? 0 | 0;
@@ -36,14 +43,41 @@ define("values/string", () => {
if (start < 0) start = 0;
length = (length ?? this.length - start) | 0;
return this.substring(start, length + start);
const end = length + start;
const res = [];
for (let i = start; i < end; i++) {
if (i >= 0 && i < this.length) res[res.length] = this[i];
}
return internals.stringFromStrings(res);
},
toLowerCase() {
return env.internals.toLower(this + '');
// TODO: Implement localization
const res = [];
for (let i = 0; i < this.length; i++) {
const c = internals.char(this[i]);
if (c >= 65 && c <= 90) res[i] = c - 65 + 97;
else res[i] = c;
}
return internals.stringFromChars(res);
},
toUpperCase() {
return env.internals.toUpper(this + '');
// TODO: Implement localization
const res = [];
for (let i = 0; i < this.length; i++) {
const c = internals.char(this[i]);
if (c >= 97 && c <= 122) res[i] = c - 97 + 65;
else res[i] = c;
}
return internals.stringFromChars(res);
},
charAt(pos) {
@@ -57,9 +91,14 @@ define("values/string", () => {
return this[pos];
},
charCodeAt(pos) {
var res = this.charAt(pos);
if (res === '') return NaN;
else return env.internals.toCharCode(res);
if (typeof this !== 'string') {
if (this instanceof String) return (this as any).value.charAt(pos);
else throw new Error('This function may be used only with primitive or object strings.');
}
pos = pos | 0;
if (pos < 0 || pos >= this.length) return 0 / 0;
return internals.char(this[pos]);
},
startsWith(term, pos) {
@@ -68,7 +107,15 @@ define("values/string", () => {
else throw new Error('This function may be used only with primitive or object strings.');
}
pos = pos! | 0;
return env.internals.startsWith(this, term + '', pos);
term = term + "";
if (pos < 0 || this.length < term.length + pos) return false;
for (let i = 0; i < term.length; i++) {
if (this[i + pos] !== term[i]) return false;
}
return true;
},
endsWith(term, pos) {
if (typeof this !== 'string') {
@@ -76,7 +123,17 @@ define("values/string", () => {
else throw new Error('This function may be used only with primitive or object strings.');
}
pos = (pos ?? this.length) | 0;
return env.internals.endsWith(this, term + '', pos);
term = term + "";
const start = pos - term.length;
if (start < 0 || this.length < term.length + start) return false;
for (let i = 0; i < term.length; i++) {
if (this[i + start] !== term[i]) return false;
}
return true;
},
indexOf(term: any, start) {
@@ -189,9 +246,9 @@ define("values/string", () => {
}
});
setProps(String, env, {
setProps(String, {
fromCharCode(val) {
return env.internals.fromCharCode(val | 0);
return internals.stringFromChars([val | 0]);
},
})
@@ -202,7 +259,7 @@ define("values/string", () => {
else throw new Error('This function may be used only with primitive or object strings.');
}
return env.internals.strlen(this);
return internals.strlen(this);
},
configurable: true,
enumerable: false,

View File

@@ -1,31 +1,34 @@
define("values/symbol", () => {
const symbols: Record<string, symbol> = { };
var Symbol = env.global.Symbol = function(this: any, val?: string) {
if (this !== undefined && this !== null) throw new TypeError("Symbol may not be called with 'new'.");
if (typeof val !== 'string' && val !== undefined) throw new TypeError('val must be a string or undefined.');
return env.internals.symbol(val, true);
return internals.symbol(val);
} as SymbolConstructor;
Symbol.prototype = env.internals.symbolProto;
setConstr(Symbol.prototype, Symbol, env);
(Symbol as any).typeName = Symbol("Symbol.name");
(Symbol as any).replace = Symbol('Symbol.replace');
(Symbol as any).match = Symbol('Symbol.match');
(Symbol as any).matchAll = Symbol('Symbol.matchAll');
(Symbol as any).split = Symbol('Symbol.split');
(Symbol as any).search = Symbol('Symbol.search');
(Symbol as any).iterator = Symbol('Symbol.iterator');
(Symbol as any).asyncIterator = Symbol('Symbol.asyncIterator');
env.setProto('symbol', Symbol.prototype);
setConstr(Symbol.prototype, Symbol);
setProps(Symbol, env, {
setProps(Symbol, {
for(key) {
if (typeof key !== 'string' && key !== undefined) throw new TypeError('key must be a string or undefined.');
return env.internals.symbol(key, false);
if (key in symbols) return symbols[key];
else return symbols[key] = internals.symbol(key);
},
keyFor(sym) {
if (typeof sym !== 'symbol') throw new TypeError('sym must be a symbol.');
return env.internals.symStr(sym);
return internals.symbolToString(sym);
},
typeName: Symbol('Symbol.name') as any,
typeName: Symbol("Symbol.name") as any,
replace: Symbol('Symbol.replace') as any,
match: Symbol('Symbol.match') as any,
matchAll: Symbol('Symbol.matchAll') as any,
split: Symbol('Symbol.split') as any,
search: Symbol('Symbol.search') as any,
iterator: Symbol('Symbol.iterator') as any,
asyncIterator: Symbol('Symbol.asyncIterator') as any,
});
env.global.Object.defineProperty(Object.prototype, Symbol.typeName, { value: 'Object' });