Create environments #4
11
lib/core.ts
11
lib/core.ts
@ -29,9 +29,14 @@ interface Internals {
|
|||||||
extensible(obj: object): boolean;
|
extensible(obj: object): boolean;
|
||||||
|
|
||||||
sort(arr: any[], comaprator: (a: any, b: any) => number): void;
|
sort(arr: any[], comaprator: (a: any, b: any) => number): void;
|
||||||
|
|
||||||
|
constructor: {
|
||||||
|
log(...args: any[]): void;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var env: Environment = arguments[0], internals: Internals = arguments[1];
|
// @ts-ignore
|
||||||
|
var env: Environment = arguments[0], internals: Internals = arguments[1], log = internals.constructor.log;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
run('values/object');
|
run('values/object');
|
||||||
@ -47,7 +52,9 @@ try {
|
|||||||
run('set');
|
run('set');
|
||||||
run('regex');
|
run('regex');
|
||||||
run('timeout');
|
run('timeout');
|
||||||
|
|
||||||
|
env.global.log = log;
|
||||||
|
|
||||||
log('Loaded polyfills!');
|
log('Loaded polyfills!');
|
||||||
}
|
}
|
||||||
catch (e: any) {
|
catch (e: any) {
|
||||||
|
11
lib/map.ts
11
lib/map.ts
@ -1,10 +1,11 @@
|
|||||||
define("map", () => {
|
define("map", () => {
|
||||||
const syms = { values: internals.symbol('Map.values') } as { readonly values: unique symbol };
|
const syms = { values: internals.symbol('Map.values') } as { readonly values: unique symbol };
|
||||||
|
const Object = env.global.Object;
|
||||||
|
|
||||||
class Map<KeyT, ValueT> {
|
class Map<KeyT, ValueT> {
|
||||||
[syms.values]: any = {};
|
[syms.values]: any = {};
|
||||||
|
|
||||||
public [Symbol.iterator](): IterableIterator<[KeyT, ValueT]> {
|
public [env.global.Symbol.iterator](): IterableIterator<[KeyT, ValueT]> {
|
||||||
return this.entries();
|
return this.entries();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ define("map", () => {
|
|||||||
if (i >= keys.length) return { done: true };
|
if (i >= keys.length) return { done: true };
|
||||||
else return { done: false, value: [ keys[i], this[syms.values][keys[i++]] ] }
|
else return { done: false, value: [ keys[i], this[syms.values][keys[i++]] ] }
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public keys(): IterableIterator<KeyT> {
|
public keys(): IterableIterator<KeyT> {
|
||||||
@ -40,7 +41,7 @@ define("map", () => {
|
|||||||
if (i >= keys.length) return { done: true };
|
if (i >= keys.length) return { done: true };
|
||||||
else return { done: false, value: keys[i] }
|
else return { done: false, value: keys[i] }
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public values(): IterableIterator<ValueT> {
|
public values(): IterableIterator<ValueT> {
|
||||||
@ -52,7 +53,7 @@ define("map", () => {
|
|||||||
if (i >= keys.length) return { done: true };
|
if (i >= keys.length) return { done: true };
|
||||||
else return { done: false, value: this[syms.values][keys[i++]] }
|
else return { done: false, value: this[syms.values][keys[i++]] }
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ define("map", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public constructor(iterable: Iterable<[KeyT, ValueT]>) {
|
public constructor(iterable: Iterable<[KeyT, ValueT]>) {
|
||||||
const it = iterable[Symbol.iterator]();
|
const it = iterable[env.global.Symbol.iterator]();
|
||||||
|
|
||||||
for (let el = it.next(); !el.done; el = it.next()) {
|
for (let el = it.next(); !el.done; el = it.next()) {
|
||||||
this[syms.values][el.value[0]] = el.value[1];
|
this[syms.values][el.value[0]] = el.value[1];
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
define("set", () => {
|
define("set", () => {
|
||||||
const syms = { values: internals.symbol('Map.values') } as { readonly values: unique symbol };
|
const syms = { values: internals.symbol('Map.values') } as { readonly values: unique symbol };
|
||||||
|
const Object = env.global.Object;
|
||||||
|
|
||||||
class Set<T> {
|
class Set<T> {
|
||||||
[syms.values]: any = {};
|
[syms.values]: any = {};
|
||||||
|
|
||||||
public [Symbol.iterator](): IterableIterator<[T, T]> {
|
public [env.global.Symbol.iterator](): IterableIterator<[T, T]> {
|
||||||
return this.entries();
|
return this.entries();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ define("set", () => {
|
|||||||
if (i >= keys.length) return { done: true };
|
if (i >= keys.length) return { done: true };
|
||||||
else return { done: false, value: [ keys[i], keys[i] ] }
|
else return { done: false, value: [ keys[i], keys[i] ] }
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public keys(): IterableIterator<T> {
|
public keys(): IterableIterator<T> {
|
||||||
@ -40,7 +41,7 @@ define("set", () => {
|
|||||||
if (i >= keys.length) return { done: true };
|
if (i >= keys.length) return { done: true };
|
||||||
else return { done: false, value: keys[i] }
|
else return { done: false, value: keys[i] }
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public values(): IterableIterator<T> {
|
public values(): IterableIterator<T> {
|
||||||
@ -68,7 +69,7 @@ define("set", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public constructor(iterable: Iterable<T>) {
|
public constructor(iterable: Iterable<T>) {
|
||||||
const it = iterable[Symbol.iterator]();
|
const it = iterable[env.global.Symbol.iterator]();
|
||||||
|
|
||||||
for (let el = it.next(); !el.done; el = it.next()) {
|
for (let el = it.next(); !el.done; el = it.next()) {
|
||||||
this[syms.values][el.value] = undefined;
|
this[syms.values][el.value] = undefined;
|
||||||
|
@ -16,14 +16,14 @@ define("values/array", () => {
|
|||||||
} as ArrayConstructor;
|
} as ArrayConstructor;
|
||||||
|
|
||||||
env.setProto('array', Array.prototype);
|
env.setProto('array', Array.prototype);
|
||||||
(Array.prototype as any)[Symbol.typeName] = "Array";
|
(Array.prototype as any)[env.global.Symbol.typeName] = "Array";
|
||||||
setConstr(Array.prototype, Array);
|
setConstr(Array.prototype, Array);
|
||||||
|
|
||||||
setProps(Array.prototype, {
|
setProps(Array.prototype, {
|
||||||
[Symbol.iterator]: function() {
|
[env.global.Symbol.iterator]: function() {
|
||||||
return this.values();
|
return this.values();
|
||||||
},
|
},
|
||||||
[Symbol.typeName]: "Array",
|
[env.global.Symbol.typeName]: "Array",
|
||||||
|
|
||||||
values() {
|
values() {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
@ -35,7 +35,7 @@ define("values/array", () => {
|
|||||||
}
|
}
|
||||||
return { done: true, value: undefined };
|
return { done: true, value: undefined };
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
keys() {
|
keys() {
|
||||||
@ -48,7 +48,7 @@ define("values/array", () => {
|
|||||||
}
|
}
|
||||||
return { done: true, value: undefined };
|
return { done: true, value: undefined };
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
entries() {
|
entries() {
|
||||||
@ -61,7 +61,7 @@ define("values/array", () => {
|
|||||||
}
|
}
|
||||||
return { done: true, value: undefined };
|
return { done: true, value: undefined };
|
||||||
},
|
},
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
concat() {
|
concat() {
|
||||||
|
@ -117,7 +117,7 @@ define("values/function", () => {
|
|||||||
},
|
},
|
||||||
return: (value) => new Promise((res, rej) => next(res, rej, 'ret', value)),
|
return: (value) => new Promise((res, rej) => next(res, rej, 'ret', value)),
|
||||||
throw: (value) => new Promise((res, rej) => next(res, rej, 'err', value)),
|
throw: (value) => new Promise((res, rej) => next(res, rej, 'err', value)),
|
||||||
[Symbol.asyncIterator]() { return this; }
|
[env.global.Symbol.asyncIterator]() { return this; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -131,7 +131,7 @@ define("values/function", () => {
|
|||||||
next: (...args) => internals.apply(it.next, it, args),
|
next: (...args) => internals.apply(it.next, it, args),
|
||||||
return: (val) => internals.apply(it.next, it, [val]),
|
return: (val) => internals.apply(it.next, it, [val]),
|
||||||
throw: (val) => internals.apply(it.next, it, [val]),
|
throw: (val) => internals.apply(it.next, it, [val]),
|
||||||
[Symbol.iterator]() { return this; }
|
[env.global.Symbol.iterator]() { return this; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,7 +216,7 @@ define("values/object", () => {
|
|||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
toString() {
|
toString() {
|
||||||
return '[object ' + (this[Symbol.typeName] ?? 'Unknown') + ']';
|
return '[object ' + (this[env.global.Symbol.typeName] ?? 'Unknown') + ']';
|
||||||
},
|
},
|
||||||
hasOwnProperty(key) {
|
hasOwnProperty(key) {
|
||||||
return Object.hasOwn(this, key);
|
return Object.hasOwn(this, key);
|
||||||
|
@ -142,9 +142,9 @@ define("values/string", () => {
|
|||||||
else throw new Error('This function may be used only with primitive or object strings.');
|
else throw new Error('This function may be used only with primitive or object strings.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof term[Symbol.search] !== 'function') term = RegExp.escape(term);
|
if (typeof term[env.global.Symbol.search] !== 'function') term = RegExp.escape(term);
|
||||||
|
|
||||||
return term[Symbol.search](this, false, start);
|
return term[env.global.Symbol.search](this, false, start);
|
||||||
},
|
},
|
||||||
lastIndexOf(term: any, start) {
|
lastIndexOf(term: any, start) {
|
||||||
if (typeof this !== 'string') {
|
if (typeof this !== 'string') {
|
||||||
@ -152,9 +152,9 @@ define("values/string", () => {
|
|||||||
else throw new Error('This function may be used only with primitive or object strings.');
|
else throw new Error('This function may be used only with primitive or object strings.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof term[Symbol.search] !== 'function') term = RegExp.escape(term);
|
if (typeof term[env.global.Symbol.search] !== 'function') term = RegExp.escape(term);
|
||||||
|
|
||||||
return term[Symbol.search](this, true, start);
|
return term[env.global.Symbol.search](this, true, start);
|
||||||
},
|
},
|
||||||
includes(term, start) {
|
includes(term, start) {
|
||||||
return this.indexOf(term, start) >= 0;
|
return this.indexOf(term, start) >= 0;
|
||||||
@ -166,9 +166,9 @@ define("values/string", () => {
|
|||||||
else throw new Error('This function may be used only with primitive or object strings.');
|
else throw new Error('This function may be used only with primitive or object strings.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof pattern[Symbol.replace] !== 'function') pattern = RegExp.escape(pattern);
|
if (typeof pattern[env.global.Symbol.replace] !== 'function') pattern = RegExp.escape(pattern);
|
||||||
|
|
||||||
return pattern[Symbol.replace](this, val);
|
return pattern[env.global.Symbol.replace](this, val);
|
||||||
},
|
},
|
||||||
replaceAll(pattern: any, val) {
|
replaceAll(pattern: any, val) {
|
||||||
if (typeof this !== 'string') {
|
if (typeof this !== 'string') {
|
||||||
@ -176,10 +176,10 @@ define("values/string", () => {
|
|||||||
else throw new Error('This function may be used only with primitive or object strings.');
|
else throw new Error('This function may be used only with primitive or object strings.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof pattern[Symbol.replace] !== 'function') pattern = RegExp.escape(pattern, "g");
|
if (typeof pattern[env.global.Symbol.replace] !== 'function') pattern = RegExp.escape(pattern, "g");
|
||||||
if (pattern instanceof RegExp && !pattern.global) pattern = new pattern.constructor(pattern.source, pattern.flags + "g");
|
if (pattern instanceof RegExp && !pattern.global) pattern = new pattern.constructor(pattern.source, pattern.flags + "g");
|
||||||
|
|
||||||
return pattern[Symbol.replace](this, val);
|
return pattern[env.global.Symbol.replace](this, val);
|
||||||
},
|
},
|
||||||
|
|
||||||
match(pattern: any) {
|
match(pattern: any) {
|
||||||
@ -188,9 +188,9 @@ define("values/string", () => {
|
|||||||
else throw new Error('This function may be used only with primitive or object strings.');
|
else throw new Error('This function may be used only with primitive or object strings.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof pattern[Symbol.match] !== 'function') pattern = RegExp.escape(pattern);
|
if (typeof pattern[env.global.Symbol.match] !== 'function') pattern = RegExp.escape(pattern);
|
||||||
|
|
||||||
return pattern[Symbol.match](this);
|
return pattern[env.global.Symbol.match](this);
|
||||||
},
|
},
|
||||||
matchAll(pattern: any) {
|
matchAll(pattern: any) {
|
||||||
if (typeof this !== 'string') {
|
if (typeof this !== 'string') {
|
||||||
@ -198,10 +198,10 @@ define("values/string", () => {
|
|||||||
else throw new Error('This function may be used only with primitive or object strings.');
|
else throw new Error('This function may be used only with primitive or object strings.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof pattern[Symbol.match] !== 'function') pattern = RegExp.escape(pattern, "g");
|
if (typeof pattern[env.global.Symbol.match] !== 'function') pattern = RegExp.escape(pattern, "g");
|
||||||
if (pattern instanceof RegExp && !pattern.global) pattern = new pattern.constructor(pattern.source, pattern.flags + "g");
|
if (pattern instanceof RegExp && !pattern.global) pattern = new pattern.constructor(pattern.source, pattern.flags + "g");
|
||||||
|
|
||||||
return pattern[Symbol.match](this);
|
return pattern[env.global.Symbol.match](this);
|
||||||
},
|
},
|
||||||
|
|
||||||
split(pattern: any, lim, sensible) {
|
split(pattern: any, lim, sensible) {
|
||||||
@ -210,9 +210,9 @@ define("values/string", () => {
|
|||||||
else throw new Error('This function may be used only with primitive or object strings.');
|
else throw new Error('This function may be used only with primitive or object strings.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof pattern[Symbol.split] !== 'function') pattern = RegExp.escape(pattern, "g");
|
if (typeof pattern[env.global.Symbol.split] !== 'function') pattern = RegExp.escape(pattern, "g");
|
||||||
|
|
||||||
return pattern[Symbol.split](this, lim, sensible);
|
return pattern[env.global.Symbol.split](this, lim, sensible);
|
||||||
},
|
},
|
||||||
slice(start, end) {
|
slice(start, end) {
|
||||||
if (typeof this !== 'string') {
|
if (typeof this !== 'string') {
|
||||||
|
@ -31,6 +31,6 @@ define("values/symbol", () => {
|
|||||||
asyncIterator: Symbol('Symbol.asyncIterator') as any,
|
asyncIterator: Symbol('Symbol.asyncIterator') as any,
|
||||||
});
|
});
|
||||||
|
|
||||||
env.global.Object.defineProperty(Object.prototype, Symbol.typeName, { value: 'Object' });
|
internals.defineField(env.global.Object.prototype, Symbol.typeName, 'Object', false, false, false);
|
||||||
env.global.Object.defineProperty(env.global, Symbol.typeName, { value: 'Window' });
|
internals.defineField(env.global, Symbol.typeName, 'Window', false, false, false);
|
||||||
});
|
});
|
@ -6,12 +6,11 @@ import java.io.InputStream;
|
|||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.MessageContext;
|
||||||
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.Engine;
|
import me.topchetoeu.jscript.engine.Engine;
|
||||||
import me.topchetoeu.jscript.engine.Environment;
|
import me.topchetoeu.jscript.engine.FunctionContext;
|
||||||
import me.topchetoeu.jscript.engine.values.NativeFunction;
|
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
import me.topchetoeu.jscript.engine.values.Values;
|
||||||
import me.topchetoeu.jscript.events.Observer;
|
import me.topchetoeu.jscript.events.Observer;
|
||||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||||
@ -22,7 +21,7 @@ import me.topchetoeu.jscript.polyfills.Internals;
|
|||||||
public class Main {
|
public class Main {
|
||||||
static Thread task;
|
static Thread task;
|
||||||
static Engine engine;
|
static Engine engine;
|
||||||
static Environment env;
|
static FunctionContext env;
|
||||||
|
|
||||||
public static String streamToString(InputStream in) {
|
public static String streamToString(InputStream in) {
|
||||||
try {
|
try {
|
||||||
@ -59,7 +58,7 @@ public class Main {
|
|||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
if (err instanceof EngineException) {
|
if (err instanceof EngineException) {
|
||||||
System.out.println("Uncaught " + ((EngineException)err).toString(new CallContext(engine, env)));
|
System.out.println("Uncaught " + ((EngineException)err).toString(new Context(null, new MessageContext(engine))));
|
||||||
}
|
}
|
||||||
else if (err instanceof SyntaxException) {
|
else if (err instanceof SyntaxException) {
|
||||||
System.out.println("Syntax error:" + ((SyntaxException)err).msg);
|
System.out.println("Syntax error:" + ((SyntaxException)err).msg);
|
||||||
@ -86,7 +85,8 @@ public class Main {
|
|||||||
System.out.println(String.format("Running %s v%s by %s", Metadata.NAME, Metadata.VERSION, Metadata.AUTHOR));
|
System.out.println(String.format("Running %s v%s by %s", Metadata.NAME, Metadata.VERSION, Metadata.AUTHOR));
|
||||||
var in = new BufferedReader(new InputStreamReader(System.in));
|
var in = new BufferedReader(new InputStreamReader(System.in));
|
||||||
engine = new Engine();
|
engine = new Engine();
|
||||||
env = new Environment(null, null, null);
|
env = new FunctionContext(null, null, null);
|
||||||
|
var builderEnv = new FunctionContext(null, new NativeTypeRegister(), null);
|
||||||
var exited = new boolean[1];
|
var exited = new boolean[1];
|
||||||
|
|
||||||
env.global.define("exit", ctx -> {
|
env.global.define("exit", ctx -> {
|
||||||
@ -103,16 +103,8 @@ public class Main {
|
|||||||
throw new EngineException("Couldn't open do.js");
|
throw new EngineException("Couldn't open do.js");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
env.global.define(true, new NativeFunction("log", (el, t, _args) -> {
|
|
||||||
for (var obj : _args) Values.printValue(el, obj);
|
|
||||||
System.out.println();
|
|
||||||
return null;
|
|
||||||
}));
|
|
||||||
|
|
||||||
var builderEnv = env.child();
|
engine.pushMsg(false, new Context(builderEnv, new MessageContext(engine)), "core.js", resourceToString("js/core.js"), null, env, new Internals()).toObservable().on(valuePrinter);
|
||||||
builderEnv.wrappersProvider = new NativeTypeRegister();
|
|
||||||
|
|
||||||
engine.pushMsg(false, Map.of(), builderEnv, "core.js", resourceToString("js/core.js"), null, env, new Internals());
|
|
||||||
|
|
||||||
task = engine.start();
|
task = engine.start();
|
||||||
var reader = new Thread(() -> {
|
var reader = new Thread(() -> {
|
||||||
@ -122,7 +114,7 @@ public class Main {
|
|||||||
var raw = in.readLine();
|
var raw = in.readLine();
|
||||||
|
|
||||||
if (raw == null) break;
|
if (raw == null) break;
|
||||||
engine.pushMsg(false, Map.of(), env, "<stdio>", raw, null).toObservable().once(valuePrinter);
|
engine.pushMsg(false, new Context(env, new MessageContext(engine)), "<stdio>", raw, null).toObservable().once(valuePrinter);
|
||||||
}
|
}
|
||||||
catch (EngineException e) {
|
catch (EngineException e) {
|
||||||
try {
|
try {
|
||||||
|
@ -70,7 +70,7 @@ public class CompoundStatement extends Statement {
|
|||||||
else return new CompoundStatement(loc(), res.toArray(Statement[]::new));
|
else return new CompoundStatement(loc(), res.toArray(Statement[]::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompoundStatement(Location loc, Statement... statements) {
|
public CompoundStatement(Location loc, Statement ...statements) {
|
||||||
super(loc);
|
super(loc);
|
||||||
this.statements = statements;
|
this.statements = statements;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ public class Instruction {
|
|||||||
return params[i].equals(arg);
|
return params[i].equals(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Instruction(Location location, Type type, Object... params) {
|
private Instruction(Location location, Type type, Object ...params) {
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.params = params;
|
this.params = params;
|
||||||
|
@ -31,12 +31,12 @@ public class CallStatement extends Statement {
|
|||||||
target.add(Instruction.call(args.length).locate(loc()).setDebug(true));
|
target.add(Instruction.call(args.length).locate(loc()).setDebug(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallStatement(Location loc, Statement func, Statement... args) {
|
public CallStatement(Location loc, Statement func, Statement ...args) {
|
||||||
super(loc);
|
super(loc);
|
||||||
this.func = func;
|
this.func = func;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
}
|
}
|
||||||
public CallStatement(Location loc, Statement obj, Object key, Statement... args) {
|
public CallStatement(Location loc, Statement obj, Object key, Statement ...args) {
|
||||||
super(loc);
|
super(loc);
|
||||||
this.func = new IndexStatement(loc, obj, new ConstantStatement(loc, key));
|
this.func = new IndexStatement(loc, obj, new ConstantStatement(loc, key));
|
||||||
this.args = args;
|
this.args = args;
|
||||||
|
@ -24,7 +24,7 @@ public class NewStatement extends Statement {
|
|||||||
target.add(Instruction.callNew(args.length).locate(loc()).setDebug(true));
|
target.add(Instruction.callNew(args.length).locate(loc()).setDebug(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public NewStatement(Location loc, Statement func, Statement... args) {
|
public NewStatement(Location loc, Statement func, Statement ...args) {
|
||||||
super(loc);
|
super(loc);
|
||||||
this.func = func;
|
this.func = func;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
|
@ -63,7 +63,7 @@ public class OperationStatement extends Statement {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationStatement(Location loc, Operation operation, Statement... args) {
|
public OperationStatement(Location loc, Operation operation, Statement ...args) {
|
||||||
super(loc);
|
super(loc);
|
||||||
this.operation = operation;
|
this.operation = operation;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
package me.topchetoeu.jscript.engine;
|
|
||||||
|
|
||||||
import me.topchetoeu.jscript.Location;
|
|
||||||
|
|
||||||
public class BreakpointData {
|
|
||||||
public final Location loc;
|
|
||||||
public final CallContext ctx;
|
|
||||||
|
|
||||||
public BreakpointData(Location loc, CallContext ctx) {
|
|
||||||
this.loc = loc;
|
|
||||||
this.ctx = ctx;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
package me.topchetoeu.jscript.engine;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public class CallContext {
|
|
||||||
public static final class DataKey<T> {}
|
|
||||||
|
|
||||||
public final Engine engine;
|
|
||||||
public Environment environment;
|
|
||||||
private final Map<DataKey<?>, Object> data;
|
|
||||||
|
|
||||||
public Map<DataKey<?>, Object> data() { return Collections.unmodifiableMap(data); }
|
|
||||||
|
|
||||||
public CallContext copy() {
|
|
||||||
return new CallContext(engine, environment).mergeData(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CallContext mergeData(Map<DataKey<?>, Object> objs) {
|
|
||||||
data.putAll(objs);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public <T> CallContext setData(DataKey<T> key, T val) {
|
|
||||||
if (val == null) data.remove(key);
|
|
||||||
else data.put(key, val);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public <T> T addData(DataKey<T> key, T val) {
|
|
||||||
if (data.containsKey(key)) return (T)data.get(key);
|
|
||||||
else {
|
|
||||||
if (val == null) data.remove(key);
|
|
||||||
else data.put(key, val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public <T> T getData(DataKey<T> key) {
|
|
||||||
return getData(key, null);
|
|
||||||
}
|
|
||||||
public <T> T getData(DataKey<T> key, T defaultVal) {
|
|
||||||
if (!hasData(key)) return defaultVal;
|
|
||||||
else return (T)data.get(key);
|
|
||||||
}
|
|
||||||
public boolean hasData(DataKey<?> key) { return data.containsKey(key); }
|
|
||||||
|
|
||||||
public CallContext changeData(DataKey<Integer> key, int n, int start) {
|
|
||||||
return setData(key, getData(key, start) + n);
|
|
||||||
}
|
|
||||||
public CallContext changeData(DataKey<Integer> key, int n) {
|
|
||||||
return changeData(key, n, 0);
|
|
||||||
}
|
|
||||||
public CallContext changeData(DataKey<Integer> key) {
|
|
||||||
return changeData(key, 1, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CallContext(Engine engine, Environment env) {
|
|
||||||
this.engine = engine;
|
|
||||||
this.data = new Hashtable<>();
|
|
||||||
this.environment = env;
|
|
||||||
}
|
|
||||||
public CallContext(CallContext parent, Environment env) {
|
|
||||||
this.engine = parent.engine;
|
|
||||||
this.data = parent.data;
|
|
||||||
this.environment = env;
|
|
||||||
}
|
|
||||||
}
|
|
11
src/me/topchetoeu/jscript/engine/Context.java
Normal file
11
src/me/topchetoeu/jscript/engine/Context.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package me.topchetoeu.jscript.engine;
|
||||||
|
|
||||||
|
public class Context {
|
||||||
|
public final FunctionContext function;
|
||||||
|
public final MessageContext message;
|
||||||
|
|
||||||
|
public Context(FunctionContext funcCtx, MessageContext msgCtx) {
|
||||||
|
this.function = funcCtx;
|
||||||
|
this.message = msgCtx;
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +0,0 @@
|
|||||||
package me.topchetoeu.jscript.engine;
|
|
||||||
|
|
||||||
public enum DebugCommand {
|
|
||||||
NORMAL,
|
|
||||||
STEP_OVER,
|
|
||||||
STEP_OUT,
|
|
||||||
STEP_INTO,
|
|
||||||
}
|
|
@ -3,7 +3,6 @@ package me.topchetoeu.jscript.engine;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext.DataKey;
|
|
||||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
import me.topchetoeu.jscript.engine.values.Values;
|
||||||
import me.topchetoeu.jscript.events.Awaitable;
|
import me.topchetoeu.jscript.events.Awaitable;
|
||||||
@ -15,16 +14,19 @@ public class Engine {
|
|||||||
private class UncompiledFunction extends FunctionValue {
|
private class UncompiledFunction extends FunctionValue {
|
||||||
public final String filename;
|
public final String filename;
|
||||||
public final String raw;
|
public final String raw;
|
||||||
|
public final FunctionContext ctx;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object call(CallContext ctx, Object thisArg, Object... args) throws InterruptedException {
|
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
|
||||||
|
ctx = new Context(this.ctx, ctx.message);
|
||||||
return compile(ctx, filename, raw).call(ctx, thisArg, args);
|
return compile(ctx, filename, raw).call(ctx, thisArg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UncompiledFunction(String filename, String raw) {
|
public UncompiledFunction(FunctionContext ctx, String filename, String raw) {
|
||||||
super(filename, 0);
|
super(filename, 0);
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
this.raw = raw;
|
this.raw = raw;
|
||||||
|
this.ctx = ctx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,14 +34,12 @@ public class Engine {
|
|||||||
public final FunctionValue func;
|
public final FunctionValue func;
|
||||||
public final Object thisArg;
|
public final Object thisArg;
|
||||||
public final Object[] args;
|
public final Object[] args;
|
||||||
public final Map<DataKey<?>, Object> data;
|
|
||||||
public final DataNotifier<Object> notifier = new DataNotifier<>();
|
public final DataNotifier<Object> notifier = new DataNotifier<>();
|
||||||
public final Environment env;
|
public final MessageContext ctx;
|
||||||
|
|
||||||
public Task(Environment env, FunctionValue func, Map<DataKey<?>, Object> data, Object thisArg, Object[] args) {
|
public Task(MessageContext ctx, FunctionValue func, Object thisArg, Object[] args) {
|
||||||
this.env = env;
|
this.ctx = ctx;
|
||||||
this.func = func;
|
this.func = func;
|
||||||
this.data = data;
|
|
||||||
this.thisArg = thisArg;
|
this.thisArg = thisArg;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ public class Engine {
|
|||||||
|
|
||||||
private void runTask(Task task) throws InterruptedException {
|
private void runTask(Task task) throws InterruptedException {
|
||||||
try {
|
try {
|
||||||
task.notifier.next(task.func.call(new CallContext(this, task.env).mergeData(task.data), task.thisArg, task.args));
|
task.notifier.next(task.func.call(new Context(null, new MessageContext(this)), task.thisArg, task.args));
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) {
|
catch (InterruptedException e) {
|
||||||
task.notifier.error(new RuntimeException(e));
|
task.notifier.error(new RuntimeException(e));
|
||||||
@ -110,19 +110,19 @@ public class Engine {
|
|||||||
return this.thread != null;
|
return this.thread != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Awaitable<Object> pushMsg(boolean micro, Map<DataKey<?>, Object> data, Environment env, FunctionValue func, Object thisArg, Object... args) {
|
public Awaitable<Object> pushMsg(boolean micro, MessageContext ctx, FunctionValue func, Object thisArg, Object ...args) {
|
||||||
var msg = new Task(env, func, data, thisArg, args);
|
var msg = new Task(ctx, func, thisArg, args);
|
||||||
if (micro) microTasks.addLast(msg);
|
if (micro) microTasks.addLast(msg);
|
||||||
else macroTasks.addLast(msg);
|
else macroTasks.addLast(msg);
|
||||||
return msg.notifier;
|
return msg.notifier;
|
||||||
}
|
}
|
||||||
public Awaitable<Object> pushMsg(boolean micro, Map<DataKey<?>, Object> data, Environment env, String filename, String raw, Object thisArg, Object... args) {
|
public Awaitable<Object> pushMsg(boolean micro, Context ctx, String filename, String raw, Object thisArg, Object ...args) {
|
||||||
return pushMsg(micro, data, env, new UncompiledFunction(filename, raw), thisArg, args);
|
return pushMsg(micro, ctx.message, new UncompiledFunction(ctx.function, filename, raw), thisArg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FunctionValue compile(CallContext ctx, String filename, String raw) throws InterruptedException {
|
public FunctionValue compile(Context ctx, String filename, String raw) throws InterruptedException {
|
||||||
var res = Values.toString(ctx, ctx.environment.compile.call(ctx, null, raw, filename));
|
var res = Values.toString(ctx, ctx.function.compile.call(ctx, null, raw, filename));
|
||||||
return Parsing.compile(ctx.environment, filename, res);
|
return Parsing.compile(ctx.function, filename, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public Engine() {
|
// public Engine() {
|
||||||
|
@ -11,7 +11,7 @@ import me.topchetoeu.jscript.interop.Native;
|
|||||||
import me.topchetoeu.jscript.interop.NativeGetter;
|
import me.topchetoeu.jscript.interop.NativeGetter;
|
||||||
import me.topchetoeu.jscript.interop.NativeSetter;
|
import me.topchetoeu.jscript.interop.NativeSetter;
|
||||||
|
|
||||||
public class Environment {
|
public class FunctionContext {
|
||||||
private HashMap<String, ObjectValue> prototypes = new HashMap<>();
|
private HashMap<String, ObjectValue> prototypes = new HashMap<>();
|
||||||
public GlobalScope global;
|
public GlobalScope global;
|
||||||
public WrappersProvider wrappersProvider;
|
public WrappersProvider wrappersProvider;
|
||||||
@ -48,21 +48,21 @@ public class Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public Environment fork() {
|
public FunctionContext fork() {
|
||||||
var res = new Environment(compile, wrappersProvider, global);
|
var res = new FunctionContext(compile, wrappersProvider, global);
|
||||||
res.regexConstructor = regexConstructor;
|
res.regexConstructor = regexConstructor;
|
||||||
res.prototypes = new HashMap<>(prototypes);
|
res.prototypes = new HashMap<>(prototypes);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public Environment child() {
|
public FunctionContext child() {
|
||||||
var res = fork();
|
var res = fork();
|
||||||
res.global = res.global.globalChild();
|
res.global = res.global.globalChild();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Environment(FunctionValue compile, WrappersProvider nativeConverter, GlobalScope global) {
|
public FunctionContext(FunctionValue compile, WrappersProvider nativeConverter, GlobalScope global) {
|
||||||
if (compile == null) compile = new NativeFunction("compile", (ctx, thisArg, args) -> args.length == 0 ? "" : args[0]);
|
if (compile == null) compile = new NativeFunction("compile", (ctx, thisArg, args) -> args.length == 0 ? "" : args[0]);
|
||||||
if (nativeConverter == null) nativeConverter = new WrappersProvider() {
|
if (nativeConverter == null) nativeConverter = new WrappersProvider() {
|
||||||
public ObjectValue getConstr(Class<?> obj) {
|
public ObjectValue getConstr(Class<?> obj) {
|
33
src/me/topchetoeu/jscript/engine/MessageContext.java
Normal file
33
src/me/topchetoeu/jscript/engine/MessageContext.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package me.topchetoeu.jscript.engine;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import me.topchetoeu.jscript.engine.frame.CodeFrame;
|
||||||
|
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||||
|
|
||||||
|
public class MessageContext {
|
||||||
|
public final Engine engine;
|
||||||
|
|
||||||
|
private final ArrayList<CodeFrame> frames = new ArrayList<>();
|
||||||
|
public int maxStackFrames = 1000;
|
||||||
|
|
||||||
|
public List<CodeFrame> frames() { return Collections.unmodifiableList(frames); }
|
||||||
|
|
||||||
|
public MessageContext pushFrame(CodeFrame frame) {
|
||||||
|
this.frames.add(frame);
|
||||||
|
if (this.frames.size() > maxStackFrames) throw EngineException.ofRange("Stack overflow!");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public boolean popFrame(CodeFrame frame) {
|
||||||
|
if (this.frames.size() == 0) return false;
|
||||||
|
if (this.frames.get(this.frames.size() - 1) != frame) return false;
|
||||||
|
this.frames.remove(this.frames.size() - 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageContext(Engine engine) {
|
||||||
|
this.engine = engine;
|
||||||
|
}
|
||||||
|
}
|
@ -4,9 +4,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.Location;
|
import me.topchetoeu.jscript.Location;
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.DebugCommand;
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext.DataKey;
|
|
||||||
import me.topchetoeu.jscript.engine.scope.LocalScope;
|
import me.topchetoeu.jscript.engine.scope.LocalScope;
|
||||||
import me.topchetoeu.jscript.engine.scope.ValueVariable;
|
import me.topchetoeu.jscript.engine.scope.ValueVariable;
|
||||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||||
@ -44,11 +42,6 @@ public class CodeFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final DataKey<Integer> STACK_N_KEY = new DataKey<>();
|
|
||||||
public static final DataKey<Integer> MAX_STACK_KEY = new DataKey<>();
|
|
||||||
public static final DataKey<Boolean> STOP_AT_START_KEY = new DataKey<>();
|
|
||||||
public static final DataKey<Boolean> STEPPING_TROUGH_KEY = new DataKey<>();
|
|
||||||
|
|
||||||
public final LocalScope scope;
|
public final LocalScope scope;
|
||||||
public final Object thisArg;
|
public final Object thisArg;
|
||||||
public final Object[] args;
|
public final Object[] args;
|
||||||
@ -59,7 +52,6 @@ public class CodeFrame {
|
|||||||
public int stackPtr = 0;
|
public int stackPtr = 0;
|
||||||
public int codePtr = 0;
|
public int codePtr = 0;
|
||||||
public boolean jumpFlag = false;
|
public boolean jumpFlag = false;
|
||||||
private DebugCommand debugCmd = null;
|
|
||||||
private Location prevLoc = null;
|
private Location prevLoc = null;
|
||||||
|
|
||||||
public void addTry(int n, int catchN, int finallyN) {
|
public void addTry(int n, int catchN, int finallyN) {
|
||||||
@ -92,7 +84,7 @@ public class CodeFrame {
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
public void push(CallContext ctx, Object val) {
|
public void push(Context ctx, Object val) {
|
||||||
if (stack.length <= stackPtr) {
|
if (stack.length <= stackPtr) {
|
||||||
var newStack = new Object[stack.length * 2];
|
var newStack = new Object[stack.length * 2];
|
||||||
System.arraycopy(stack, 0, newStack, 0, stack.length);
|
System.arraycopy(stack, 0, newStack, 0, stack.length);
|
||||||
@ -101,21 +93,7 @@ public class CodeFrame {
|
|||||||
stack[stackPtr++] = Values.normalize(ctx, val);
|
stack[stackPtr++] = Values.normalize(ctx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(CallContext ctx) {
|
private Object nextNoTry(Context ctx) throws InterruptedException {
|
||||||
if (ctx.getData(STACK_N_KEY, 0) >= ctx.addData(MAX_STACK_KEY, 10000)) throw EngineException.ofRange("Stack overflow!");
|
|
||||||
ctx.changeData(STACK_N_KEY);
|
|
||||||
|
|
||||||
// var debugState = ctx.getData(Engine.DEBUG_STATE_KEY);
|
|
||||||
// if (debugState != null) debugState.pushFrame(this);
|
|
||||||
}
|
|
||||||
public void end(CallContext ctx) {
|
|
||||||
ctx.changeData(STACK_N_KEY, -1);
|
|
||||||
|
|
||||||
// var debugState = ctx.getData(Engine.DEBUG_STATE_KEY);
|
|
||||||
// if (debugState != null) debugState.popFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object nextNoTry(CallContext ctx) throws InterruptedException {
|
|
||||||
if (Thread.currentThread().isInterrupted()) throw new InterruptedException();
|
if (Thread.currentThread().isInterrupted()) throw new InterruptedException();
|
||||||
if (codePtr < 0 || codePtr >= function.body.length) return null;
|
if (codePtr < 0 || codePtr >= function.body.length) return null;
|
||||||
|
|
||||||
@ -124,39 +102,16 @@ public class CodeFrame {
|
|||||||
var loc = instr.location;
|
var loc = instr.location;
|
||||||
if (loc != null) prevLoc = loc;
|
if (loc != null) prevLoc = loc;
|
||||||
|
|
||||||
// var debugState = ctx.getData(Engine.DEBUG_STATE_KEY);
|
|
||||||
// if (debugCmd == null) {
|
|
||||||
// if (ctx.getData(STOP_AT_START_KEY, false)) debugCmd = DebugCommand.STEP_OVER;
|
|
||||||
// else debugCmd = DebugCommand.NORMAL;
|
|
||||||
|
|
||||||
// if (debugState != null) debugState.pushFrame(this);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (debugState != null && loc != null) {
|
|
||||||
// if (
|
|
||||||
// instr.type == Type.NOP && instr.match("debug") || debugState.breakpoints.contains(loc) || (
|
|
||||||
// ctx.getData(STEPPING_TROUGH_KEY, false) &&
|
|
||||||
// (debugCmd == DebugCommand.STEP_INTO || debugCmd == DebugCommand.STEP_OVER)
|
|
||||||
// )
|
|
||||||
// ) {
|
|
||||||
// ctx.setData(STEPPING_TROUGH_KEY, true);
|
|
||||||
|
|
||||||
// debugState.breakpointNotifier.next(new BreakpointData(loc, ctx));
|
|
||||||
// debugCmd = debugState.commandNotifier.toAwaitable().await();
|
|
||||||
// if (debugCmd == DebugCommand.NORMAL) ctx.setData(STEPPING_TROUGH_KEY, false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.jumpFlag = false;
|
this.jumpFlag = false;
|
||||||
return Runners.exec(ctx, debugCmd, instr, this);
|
return Runners.exec(ctx, instr, this);
|
||||||
}
|
}
|
||||||
catch (EngineException e) {
|
catch (EngineException e) {
|
||||||
throw e.add(function.name, prevLoc);
|
throw e.add(function.name, prevLoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next(CallContext ctx, Object prevReturn, Object prevError) throws InterruptedException {
|
public Object next(Context ctx, Object prevReturn, Object prevError) throws InterruptedException {
|
||||||
TryCtx tryCtx = null;
|
TryCtx tryCtx = null;
|
||||||
if (prevError != Runners.NO_RETURN) prevReturn = Runners.NO_RETURN;
|
if (prevError != Runners.NO_RETURN) prevReturn = Runners.NO_RETURN;
|
||||||
|
|
||||||
@ -256,6 +211,7 @@ public class CodeFrame {
|
|||||||
catch (EngineException e) {
|
catch (EngineException e) {
|
||||||
if (tryCtx.hasCatch) {
|
if (tryCtx.hasCatch) {
|
||||||
tryCtx.state = TryCtx.STATE_CATCH;
|
tryCtx.state = TryCtx.STATE_CATCH;
|
||||||
|
tryCtx.err = e;
|
||||||
codePtr = tryCtx.catchStart;
|
codePtr = tryCtx.catchStart;
|
||||||
scope.catchVars.add(new ValueVariable(false, e.value));
|
scope.catchVars.add(new ValueVariable(false, e.value));
|
||||||
return Runners.NO_RETURN;
|
return Runners.NO_RETURN;
|
||||||
@ -280,6 +236,7 @@ public class CodeFrame {
|
|||||||
else return res;
|
else return res;
|
||||||
}
|
}
|
||||||
catch (EngineException e) {
|
catch (EngineException e) {
|
||||||
|
e.cause = tryCtx.err;
|
||||||
if (tryCtx.hasFinally) {
|
if (tryCtx.hasFinally) {
|
||||||
tryCtx.err = e;
|
tryCtx.err = e;
|
||||||
tryCtx.state = TryCtx.STATE_FINALLY_THREW;
|
tryCtx.state = TryCtx.STATE_FINALLY_THREW;
|
||||||
@ -290,23 +247,32 @@ public class CodeFrame {
|
|||||||
codePtr = tryCtx.finallyStart;
|
codePtr = tryCtx.finallyStart;
|
||||||
return Runners.NO_RETURN;
|
return Runners.NO_RETURN;
|
||||||
}
|
}
|
||||||
|
else if (tryCtx.state == TryCtx.STATE_FINALLY_THREW) {
|
||||||
|
try {
|
||||||
|
return nextNoTry(ctx);
|
||||||
|
}
|
||||||
|
catch (EngineException e) {
|
||||||
|
e.cause = tryCtx.err;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
else return nextNoTry(ctx);
|
else return nextNoTry(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object run(CallContext ctx) throws InterruptedException {
|
public Object run(Context ctx) throws InterruptedException {
|
||||||
try {
|
try {
|
||||||
start(ctx);
|
ctx.message.pushFrame(this);
|
||||||
while (true) {
|
while (true) {
|
||||||
var res = next(ctx, Runners.NO_RETURN, Runners.NO_RETURN);
|
var res = next(ctx, Runners.NO_RETURN, Runners.NO_RETURN);
|
||||||
if (res != Runners.NO_RETURN) return res;
|
if (res != Runners.NO_RETURN) return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
end(ctx);
|
ctx.message.popFrame(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeFrame(CallContext ctx, Object thisArg, Object[] args, CodeFunction func) {
|
public CodeFrame(Context ctx, Object thisArg, Object[] args, CodeFunction func) {
|
||||||
this.args = args.clone();
|
this.args = args.clone();
|
||||||
this.scope = new LocalScope(func.localsN, func.captures);
|
this.scope = new LocalScope(func.localsN, func.captures);
|
||||||
this.scope.get(0).set(null, thisArg);
|
this.scope.get(0).set(null, thisArg);
|
||||||
|
@ -3,8 +3,7 @@ package me.topchetoeu.jscript.engine.frame;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.compilation.Instruction;
|
import me.topchetoeu.jscript.compilation.Instruction;
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.DebugCommand;
|
|
||||||
import me.topchetoeu.jscript.engine.Operation;
|
import me.topchetoeu.jscript.engine.Operation;
|
||||||
import me.topchetoeu.jscript.engine.scope.ValueVariable;
|
import me.topchetoeu.jscript.engine.scope.ValueVariable;
|
||||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||||
@ -18,48 +17,45 @@ import me.topchetoeu.jscript.exceptions.EngineException;
|
|||||||
public class Runners {
|
public class Runners {
|
||||||
public static final Object NO_RETURN = new Object();
|
public static final Object NO_RETURN = new Object();
|
||||||
|
|
||||||
public static Object execReturn(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execReturn(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.codePtr++;
|
|
||||||
return frame.pop();
|
return frame.pop();
|
||||||
}
|
}
|
||||||
public static Object execSignal(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execSignal(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.codePtr++;
|
|
||||||
return new SignalValue(instr.get(0));
|
return new SignalValue(instr.get(0));
|
||||||
}
|
}
|
||||||
public static Object execThrow(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execThrow(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
throw new EngineException(frame.pop());
|
throw new EngineException(frame.pop());
|
||||||
}
|
}
|
||||||
public static Object execThrowSyntax(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execThrowSyntax(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
throw EngineException.ofSyntax((String)instr.get(0));
|
throw EngineException.ofSyntax((String)instr.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object call(CallContext ctx, DebugCommand state, Object func, Object thisArg, Object... args) throws InterruptedException {
|
private static Object call(Context ctx, Object func, Object thisArg, Object ...args) throws InterruptedException {
|
||||||
ctx.setData(CodeFrame.STOP_AT_START_KEY, state == DebugCommand.STEP_INTO);
|
|
||||||
return Values.call(ctx, func, thisArg, args);
|
return Values.call(ctx, func, thisArg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execCall(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execCall(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var callArgs = frame.take(instr.get(0));
|
var callArgs = frame.take(instr.get(0));
|
||||||
var func = frame.pop();
|
var func = frame.pop();
|
||||||
var thisArg = frame.pop();
|
var thisArg = frame.pop();
|
||||||
|
|
||||||
frame.push(ctx, call(ctx, state, func, thisArg, callArgs));
|
frame.push(ctx, call(ctx, func, thisArg, callArgs));
|
||||||
|
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execCallNew(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execCallNew(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var callArgs = frame.take(instr.get(0));
|
var callArgs = frame.take(instr.get(0));
|
||||||
var funcObj = frame.pop();
|
var funcObj = frame.pop();
|
||||||
|
|
||||||
if (Values.isFunction(funcObj) && Values.function(funcObj).special) {
|
if (Values.isFunction(funcObj) && Values.function(funcObj).special) {
|
||||||
frame.push(ctx, call(ctx, state, funcObj, null, callArgs));
|
frame.push(ctx, call(ctx, funcObj, null, callArgs));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var proto = Values.getMember(ctx, funcObj, "prototype");
|
var proto = Values.getMember(ctx, funcObj, "prototype");
|
||||||
var obj = new ObjectValue();
|
var obj = new ObjectValue();
|
||||||
obj.setPrototype(ctx, proto);
|
obj.setPrototype(ctx, proto);
|
||||||
call(ctx, state, funcObj, obj, callArgs);
|
call(ctx, funcObj, obj, callArgs);
|
||||||
frame.push(ctx, obj);
|
frame.push(ctx, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,13 +63,13 @@ public class Runners {
|
|||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execMakeVar(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execMakeVar(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var name = (String)instr.get(0);
|
var name = (String)instr.get(0);
|
||||||
frame.function.environment.global.define(name);
|
ctx.function.global.define(name);
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execDefProp(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execDefProp(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var setter = frame.pop();
|
var setter = frame.pop();
|
||||||
var getter = frame.pop();
|
var getter = frame.pop();
|
||||||
var name = frame.pop();
|
var name = frame.pop();
|
||||||
@ -88,7 +84,7 @@ public class Runners {
|
|||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execInstanceof(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execInstanceof(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var type = frame.pop();
|
var type = frame.pop();
|
||||||
var obj = frame.pop();
|
var obj = frame.pop();
|
||||||
|
|
||||||
@ -103,7 +99,7 @@ public class Runners {
|
|||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execKeys(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execKeys(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var val = frame.pop();
|
var val = frame.pop();
|
||||||
|
|
||||||
var arr = new ObjectValue();
|
var arr = new ObjectValue();
|
||||||
@ -123,13 +119,13 @@ public class Runners {
|
|||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execTry(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execTry(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
frame.addTry(instr.get(0), instr.get(1), instr.get(2));
|
frame.addTry(instr.get(0), instr.get(1), instr.get(2));
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execDup(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execDup(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
int offset = instr.get(0), count = instr.get(1);
|
int offset = instr.get(0), count = instr.get(1);
|
||||||
|
|
||||||
for (var i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
@ -139,7 +135,7 @@ public class Runners {
|
|||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execMove(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execMove(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
int offset = instr.get(0), count = instr.get(1);
|
int offset = instr.get(0), count = instr.get(1);
|
||||||
|
|
||||||
var tmp = frame.take(offset);
|
var tmp = frame.take(offset);
|
||||||
@ -151,43 +147,43 @@ public class Runners {
|
|||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadUndefined(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execLoadUndefined(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.push(ctx, null);
|
frame.push(ctx, null);
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadValue(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execLoadValue(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.push(ctx, instr.get(0));
|
frame.push(ctx, instr.get(0));
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadVar(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execLoadVar(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var i = instr.get(0);
|
var i = instr.get(0);
|
||||||
|
|
||||||
if (i instanceof String) frame.push(ctx, frame.function.environment.global.get(ctx, (String)i));
|
if (i instanceof String) frame.push(ctx, ctx.function.global.get(ctx, (String)i));
|
||||||
else frame.push(ctx, frame.scope.get((int)i).get(ctx));
|
else frame.push(ctx, frame.scope.get((int)i).get(ctx));
|
||||||
|
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadObj(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execLoadObj(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.push(ctx, new ObjectValue());
|
frame.push(ctx, new ObjectValue());
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadGlob(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execLoadGlob(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.push(ctx, frame.function.environment.global.obj);
|
frame.push(ctx, ctx.function.global.obj);
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadArr(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execLoadArr(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
var res = new ArrayValue();
|
var res = new ArrayValue();
|
||||||
res.setSize(instr.get(0));
|
res.setSize(instr.get(0));
|
||||||
frame.push(ctx, res);
|
frame.push(ctx, res);
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadFunc(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execLoadFunc(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
int n = (Integer)instr.get(0);
|
int n = (Integer)instr.get(0);
|
||||||
int localsN = (Integer)instr.get(1);
|
int localsN = (Integer)instr.get(1);
|
||||||
int len = (Integer)instr.get(2);
|
int len = (Integer)instr.get(2);
|
||||||
@ -202,18 +198,17 @@ public class Runners {
|
|||||||
var body = new Instruction[end - start];
|
var body = new Instruction[end - start];
|
||||||
System.arraycopy(frame.function.body, start, body, 0, end - start);
|
System.arraycopy(frame.function.body, start, body, 0, end - start);
|
||||||
|
|
||||||
var func = new CodeFunction("", localsN, len, frame.function.environment, captures, body);
|
var func = new CodeFunction(ctx.function, "", localsN, len, captures, body);
|
||||||
frame.push(ctx, func);
|
frame.push(ctx, func);
|
||||||
|
|
||||||
frame.codePtr += n;
|
frame.codePtr += n;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadMember(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execLoadMember(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var key = frame.pop();
|
var key = frame.pop();
|
||||||
var obj = frame.pop();
|
var obj = frame.pop();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ctx.setData(CodeFrame.STOP_AT_START_KEY, state == DebugCommand.STEP_INTO);
|
|
||||||
frame.push(ctx, Values.getMember(ctx, obj, key));
|
frame.push(ctx, Values.getMember(ctx, obj, key));
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException e) {
|
catch (IllegalArgumentException e) {
|
||||||
@ -222,54 +217,53 @@ public class Runners {
|
|||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execLoadKeyMember(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execLoadKeyMember(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
frame.push(ctx, instr.get(0));
|
frame.push(ctx, instr.get(0));
|
||||||
return execLoadMember(ctx, state, instr, frame);
|
return execLoadMember(ctx, instr, frame);
|
||||||
}
|
}
|
||||||
public static Object execLoadRegEx(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execLoadRegEx(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
frame.push(ctx, ctx.environment.regexConstructor.call(ctx, null, instr.get(0), instr.get(1)));
|
frame.push(ctx, ctx.function.regexConstructor.call(ctx, null, instr.get(0), instr.get(1)));
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execDiscard(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execDiscard(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.pop();
|
frame.pop();
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execStoreMember(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execStoreMember(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var val = frame.pop();
|
var val = frame.pop();
|
||||||
var key = frame.pop();
|
var key = frame.pop();
|
||||||
var obj = frame.pop();
|
var obj = frame.pop();
|
||||||
|
|
||||||
ctx.setData(CodeFrame.STOP_AT_START_KEY, state == DebugCommand.STEP_INTO);
|
|
||||||
if (!Values.setMember(ctx, obj, key, val)) throw EngineException.ofSyntax("Can't set member '" + key + "'.");
|
if (!Values.setMember(ctx, obj, key, val)) throw EngineException.ofSyntax("Can't set member '" + key + "'.");
|
||||||
if ((boolean)instr.get(0)) frame.push(ctx, val);
|
if ((boolean)instr.get(0)) frame.push(ctx, val);
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execStoreVar(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execStoreVar(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var val = (boolean)instr.get(1) ? frame.peek() : frame.pop();
|
var val = (boolean)instr.get(1) ? frame.peek() : frame.pop();
|
||||||
var i = instr.get(0);
|
var i = instr.get(0);
|
||||||
|
|
||||||
if (i instanceof String) frame.function.environment.global.set(ctx, (String)i, val);
|
if (i instanceof String) ctx.function.global.set(ctx, (String)i, val);
|
||||||
else frame.scope.get((int)i).set(ctx, val);
|
else frame.scope.get((int)i).set(ctx, val);
|
||||||
|
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execStoreSelfFunc(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execStoreSelfFunc(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.scope.locals[(int)instr.get(0)].set(ctx, frame.function);
|
frame.scope.locals[(int)instr.get(0)].set(ctx, frame.function);
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execJmp(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execJmp(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
frame.codePtr += (int)instr.get(0);
|
frame.codePtr += (int)instr.get(0);
|
||||||
frame.jumpFlag = true;
|
frame.jumpFlag = true;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execJmpIf(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execJmpIf(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
if (Values.toBoolean(frame.pop())) {
|
if (Values.toBoolean(frame.pop())) {
|
||||||
frame.codePtr += (int)instr.get(0);
|
frame.codePtr += (int)instr.get(0);
|
||||||
frame.jumpFlag = true;
|
frame.jumpFlag = true;
|
||||||
@ -277,7 +271,7 @@ public class Runners {
|
|||||||
else frame.codePtr ++;
|
else frame.codePtr ++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execJmpIfNot(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execJmpIfNot(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
if (Values.not(frame.pop())) {
|
if (Values.not(frame.pop())) {
|
||||||
frame.codePtr += (int)instr.get(0);
|
frame.codePtr += (int)instr.get(0);
|
||||||
frame.jumpFlag = true;
|
frame.jumpFlag = true;
|
||||||
@ -286,7 +280,7 @@ public class Runners {
|
|||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execIn(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execIn(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var obj = frame.pop();
|
var obj = frame.pop();
|
||||||
var index = frame.pop();
|
var index = frame.pop();
|
||||||
|
|
||||||
@ -294,13 +288,13 @@ public class Runners {
|
|||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execTypeof(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execTypeof(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
String name = instr.get(0);
|
String name = instr.get(0);
|
||||||
Object obj;
|
Object obj;
|
||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (frame.function.environment.global.has(ctx, name)) {
|
if (ctx.function.global.has(ctx, name)) {
|
||||||
obj = frame.function.environment.global.get(ctx, name);
|
obj = ctx.function.global.get(ctx, name);
|
||||||
}
|
}
|
||||||
else obj = null;
|
else obj = null;
|
||||||
}
|
}
|
||||||
@ -311,7 +305,7 @@ public class Runners {
|
|||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
public static Object execNop(CallContext ctx, Instruction instr, CodeFrame frame) {
|
public static Object execNop(Context ctx, Instruction instr, CodeFrame frame) {
|
||||||
if (instr.is(0, "dbg_names")) {
|
if (instr.is(0, "dbg_names")) {
|
||||||
var names = new String[instr.params.length - 1];
|
var names = new String[instr.params.length - 1];
|
||||||
for (var i = 0; i < instr.params.length - 1; i++) {
|
for (var i = 0; i < instr.params.length - 1; i++) {
|
||||||
@ -325,7 +319,7 @@ public class Runners {
|
|||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execDelete(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execDelete(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
var key = frame.pop();
|
var key = frame.pop();
|
||||||
var val = frame.pop();
|
var val = frame.pop();
|
||||||
|
|
||||||
@ -335,7 +329,7 @@ public class Runners {
|
|||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object execOperation(CallContext ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object execOperation(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
Operation op = instr.get(0);
|
Operation op = instr.get(0);
|
||||||
var args = new Object[op.operands];
|
var args = new Object[op.operands];
|
||||||
|
|
||||||
@ -346,7 +340,7 @@ public class Runners {
|
|||||||
return NO_RETURN;
|
return NO_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object exec(CallContext ctx, DebugCommand state, Instruction instr, CodeFrame frame) throws InterruptedException {
|
public static Object exec(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
|
||||||
// System.out.println(instr + "@" + instr.location);
|
// System.out.println(instr + "@" + instr.location);
|
||||||
switch (instr.type) {
|
switch (instr.type) {
|
||||||
case NOP: return execNop(ctx, instr, frame);
|
case NOP: return execNop(ctx, instr, frame);
|
||||||
@ -354,8 +348,8 @@ public class Runners {
|
|||||||
case SIGNAL: return execSignal(ctx, instr, frame);
|
case SIGNAL: return execSignal(ctx, instr, frame);
|
||||||
case THROW: return execThrow(ctx, instr, frame);
|
case THROW: return execThrow(ctx, instr, frame);
|
||||||
case THROW_SYNTAX: return execThrowSyntax(ctx, instr, frame);
|
case THROW_SYNTAX: return execThrowSyntax(ctx, instr, frame);
|
||||||
case CALL: return execCall(ctx, state, instr, frame);
|
case CALL: return execCall(ctx, instr, frame);
|
||||||
case CALL_NEW: return execCallNew(ctx, state, instr, frame);
|
case CALL_NEW: return execCallNew(ctx, instr, frame);
|
||||||
case TRY: return execTry(ctx, instr, frame);
|
case TRY: return execTry(ctx, instr, frame);
|
||||||
|
|
||||||
case DUP: return execDup(ctx, instr, frame);
|
case DUP: return execDup(ctx, instr, frame);
|
||||||
@ -365,13 +359,13 @@ public class Runners {
|
|||||||
case LOAD_OBJ: return execLoadObj(ctx, instr, frame);
|
case LOAD_OBJ: return execLoadObj(ctx, instr, frame);
|
||||||
case LOAD_ARR: return execLoadArr(ctx, instr, frame);
|
case LOAD_ARR: return execLoadArr(ctx, instr, frame);
|
||||||
case LOAD_FUNC: return execLoadFunc(ctx, instr, frame);
|
case LOAD_FUNC: return execLoadFunc(ctx, instr, frame);
|
||||||
case LOAD_MEMBER: return execLoadMember(ctx, state, instr, frame);
|
case LOAD_MEMBER: return execLoadMember(ctx, instr, frame);
|
||||||
case LOAD_VAL_MEMBER: return execLoadKeyMember(ctx, state, instr, frame);
|
case LOAD_VAL_MEMBER: return execLoadKeyMember(ctx, instr, frame);
|
||||||
case LOAD_REGEX: return execLoadRegEx(ctx, instr, frame);
|
case LOAD_REGEX: return execLoadRegEx(ctx, instr, frame);
|
||||||
case LOAD_GLOB: return execLoadGlob(ctx, instr, frame);
|
case LOAD_GLOB: return execLoadGlob(ctx, instr, frame);
|
||||||
|
|
||||||
case DISCARD: return execDiscard(ctx, instr, frame);
|
case DISCARD: return execDiscard(ctx, instr, frame);
|
||||||
case STORE_MEMBER: return execStoreMember(ctx, state, instr, frame);
|
case STORE_MEMBER: return execStoreMember(ctx, instr, frame);
|
||||||
case STORE_VAR: return execStoreVar(ctx, instr, frame);
|
case STORE_VAR: return execStoreVar(ctx, instr, frame);
|
||||||
case STORE_SELF_FUNC: return execStoreSelfFunc(ctx, instr, frame);
|
case STORE_SELF_FUNC: return execStoreSelfFunc(ctx, instr, frame);
|
||||||
case MAKE_VAR: return execMakeVar(ctx, instr, frame);
|
case MAKE_VAR: return execMakeVar(ctx, instr, frame);
|
||||||
|
@ -3,7 +3,7 @@ package me.topchetoeu.jscript.engine.scope;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||||
import me.topchetoeu.jscript.engine.values.NativeFunction;
|
import me.topchetoeu.jscript.engine.values.NativeFunction;
|
||||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
||||||
@ -15,7 +15,7 @@ public class GlobalScope implements ScopeRecord {
|
|||||||
@Override
|
@Override
|
||||||
public GlobalScope parent() { return null; }
|
public GlobalScope parent() { return null; }
|
||||||
|
|
||||||
public boolean has(CallContext ctx, String name) throws InterruptedException {
|
public boolean has(Context ctx, String name) throws InterruptedException {
|
||||||
return obj.hasMember(ctx, name, false);
|
return obj.hasMember(ctx, name, false);
|
||||||
}
|
}
|
||||||
public Object getKey(String name) {
|
public Object getKey(String name) {
|
||||||
@ -49,21 +49,21 @@ public class GlobalScope implements ScopeRecord {
|
|||||||
true, true
|
true, true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
public void define(CallContext ctx, String name, boolean readonly, Object val) {
|
public void define(Context ctx, String name, boolean readonly, Object val) {
|
||||||
obj.defineProperty(ctx, name, val, readonly, true, true);
|
obj.defineProperty(ctx, name, val, readonly, true, true);
|
||||||
}
|
}
|
||||||
public void define(String... names) {
|
public void define(String ...names) {
|
||||||
for (var n : names) define(n);
|
for (var n : names) define(n);
|
||||||
}
|
}
|
||||||
public void define(boolean readonly, FunctionValue val) {
|
public void define(boolean readonly, FunctionValue val) {
|
||||||
define(null, val.name, readonly, val);
|
define(null, val.name, readonly, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object get(CallContext ctx, String name) throws InterruptedException {
|
public Object get(Context ctx, String name) throws InterruptedException {
|
||||||
if (!obj.hasMember(ctx, name, false)) throw EngineException.ofSyntax("The variable '" + name + "' doesn't exist.");
|
if (!obj.hasMember(ctx, name, false)) throw EngineException.ofSyntax("The variable '" + name + "' doesn't exist.");
|
||||||
else return obj.getMember(ctx, name);
|
else return obj.getMember(ctx, name);
|
||||||
}
|
}
|
||||||
public void set(CallContext ctx, String name, Object val) throws InterruptedException {
|
public void set(Context ctx, String name, Object val) throws InterruptedException {
|
||||||
if (!obj.hasMember(ctx, name, false)) throw EngineException.ofSyntax("The variable '" + name + "' doesn't exist.");
|
if (!obj.hasMember(ctx, name, false)) throw EngineException.ofSyntax("The variable '" + name + "' doesn't exist.");
|
||||||
if (!obj.setMember(ctx, name, val, false)) throw EngineException.ofSyntax("The global '" + name + "' is readonly.");
|
if (!obj.setMember(ctx, name, val, false)) throw EngineException.ofSyntax("The global '" + name + "' is readonly.");
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package me.topchetoeu.jscript.engine.scope;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
|
|
||||||
public class LocalScopeRecord implements ScopeRecord {
|
public class LocalScopeRecord implements ScopeRecord {
|
||||||
public final LocalScopeRecord parent;
|
public final LocalScopeRecord parent;
|
||||||
@ -59,7 +59,7 @@ public class LocalScopeRecord implements ScopeRecord {
|
|||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
public boolean has(CallContext ctx, String name) throws InterruptedException {
|
public boolean has(Context ctx, String name) throws InterruptedException {
|
||||||
return
|
return
|
||||||
global.has(ctx, name) ||
|
global.has(ctx, name) ||
|
||||||
locals.contains(name) ||
|
locals.contains(name) ||
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.engine.scope;
|
package me.topchetoeu.jscript.engine.scope;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
import me.topchetoeu.jscript.engine.values.Values;
|
||||||
|
|
||||||
public class ValueVariable implements Variable {
|
public class ValueVariable implements Variable {
|
||||||
@ -11,12 +11,12 @@ public class ValueVariable implements Variable {
|
|||||||
public boolean readonly() { return readonly; }
|
public boolean readonly() { return readonly; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get(CallContext ctx) {
|
public Object get(Context ctx) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void set(CallContext ctx, Object val) {
|
public void set(Context ctx, Object val) {
|
||||||
if (readonly) return;
|
if (readonly) return;
|
||||||
this.value = Values.normalize(ctx, val);
|
this.value = Values.normalize(ctx, val);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package me.topchetoeu.jscript.engine.scope;
|
package me.topchetoeu.jscript.engine.scope;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
|
|
||||||
public interface Variable {
|
public interface Variable {
|
||||||
Object get(CallContext ctx) throws InterruptedException;
|
Object get(Context ctx) throws InterruptedException;
|
||||||
default boolean readonly() { return true; }
|
default boolean readonly() { return true; }
|
||||||
default void set(CallContext ctx, Object val) throws InterruptedException { }
|
default void set(Context ctx, Object val) throws InterruptedException { }
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import java.util.Collection;
|
|||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
|
|
||||||
public class ArrayValue extends ObjectValue {
|
public class ArrayValue extends ObjectValue {
|
||||||
private static final Object EMPTY = new Object();
|
private static final Object EMPTY = new Object();
|
||||||
@ -29,7 +29,7 @@ public class ArrayValue extends ObjectValue {
|
|||||||
if (res == EMPTY) return null;
|
if (res == EMPTY) return null;
|
||||||
else return res;
|
else return res;
|
||||||
}
|
}
|
||||||
public void set(CallContext ctx, int i, Object val) {
|
public void set(Context ctx, int i, Object val) {
|
||||||
if (i < 0) return;
|
if (i < 0) return;
|
||||||
|
|
||||||
while (values.size() <= i) {
|
while (values.size() <= i) {
|
||||||
@ -83,7 +83,7 @@ public class ArrayValue extends ObjectValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object getField(CallContext ctx, Object key) throws InterruptedException {
|
protected Object getField(Context ctx, Object key) throws InterruptedException {
|
||||||
if (key.equals("length")) return values.size();
|
if (key.equals("length")) return values.size();
|
||||||
if (key instanceof Number) {
|
if (key instanceof Number) {
|
||||||
var i = ((Number)key).doubleValue();
|
var i = ((Number)key).doubleValue();
|
||||||
@ -95,7 +95,7 @@ public class ArrayValue extends ObjectValue {
|
|||||||
return super.getField(ctx, key);
|
return super.getField(ctx, key);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected boolean setField(CallContext ctx, Object key, Object val) throws InterruptedException {
|
protected boolean setField(Context ctx, Object key, Object val) throws InterruptedException {
|
||||||
if (key.equals("length")) {
|
if (key.equals("length")) {
|
||||||
return setSize((int)Values.toNumber(ctx, val));
|
return setSize((int)Values.toNumber(ctx, val));
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ public class ArrayValue extends ObjectValue {
|
|||||||
return super.setField(ctx, key, val);
|
return super.setField(ctx, key, val);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasField(CallContext ctx, Object key) throws InterruptedException {
|
protected boolean hasField(Context ctx, Object key) throws InterruptedException {
|
||||||
if (key.equals("length")) return true;
|
if (key.equals("length")) return true;
|
||||||
if (key instanceof Number) {
|
if (key instanceof Number) {
|
||||||
var i = Values.number(key);
|
var i = Values.number(key);
|
||||||
@ -122,7 +122,7 @@ public class ArrayValue extends ObjectValue {
|
|||||||
return super.hasField(ctx, key);
|
return super.hasField(ctx, key);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected void deleteField(CallContext ctx, Object key) throws InterruptedException {
|
protected void deleteField(Context ctx, Object key) throws InterruptedException {
|
||||||
if (key instanceof Number) {
|
if (key instanceof Number) {
|
||||||
var i = Values.number(key);
|
var i = Values.number(key);
|
||||||
if (i >= 0 && i - Math.floor(i) == 0) {
|
if (i >= 0 && i - Math.floor(i) == 0) {
|
||||||
@ -149,12 +149,12 @@ public class ArrayValue extends ObjectValue {
|
|||||||
nonEnumerableSet.add("length");
|
nonEnumerableSet.add("length");
|
||||||
nonConfigurableSet.add("length");
|
nonConfigurableSet.add("length");
|
||||||
}
|
}
|
||||||
public ArrayValue(CallContext ctx, Object ...values) {
|
public ArrayValue(Context ctx, Object ...values) {
|
||||||
this();
|
this();
|
||||||
for (var i = 0; i < values.length; i++) this.values.add(Values.normalize(ctx, values[i]));
|
for (var i = 0; i < values.length; i++) this.values.add(Values.normalize(ctx, values[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ArrayValue of(CallContext ctx, Collection<Object> values) {
|
public static ArrayValue of(Context ctx, Collection<Object> values) {
|
||||||
return new ArrayValue(ctx, values.toArray(Object[]::new));
|
return new ArrayValue(ctx, values.toArray(Object[]::new));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package me.topchetoeu.jscript.engine.values;
|
package me.topchetoeu.jscript.engine.values;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
|
|
||||||
import me.topchetoeu.jscript.Location;
|
import me.topchetoeu.jscript.Location;
|
||||||
import me.topchetoeu.jscript.compilation.Instruction;
|
import me.topchetoeu.jscript.compilation.Instruction;
|
||||||
import me.topchetoeu.jscript.compilation.Instruction.Type;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.FunctionContext;
|
||||||
import me.topchetoeu.jscript.engine.Environment;
|
|
||||||
import me.topchetoeu.jscript.engine.frame.CodeFrame;
|
import me.topchetoeu.jscript.engine.frame.CodeFrame;
|
||||||
import me.topchetoeu.jscript.engine.scope.ValueVariable;
|
import me.topchetoeu.jscript.engine.scope.ValueVariable;
|
||||||
|
|
||||||
@ -14,10 +11,8 @@ public class CodeFunction extends FunctionValue {
|
|||||||
public final int localsN;
|
public final int localsN;
|
||||||
public final int length;
|
public final int length;
|
||||||
public final Instruction[] body;
|
public final Instruction[] body;
|
||||||
public final LinkedHashMap<Location, Integer> breakableLocToIndex = new LinkedHashMap<>();
|
|
||||||
public final LinkedHashMap<Integer, Location> breakableIndexToLoc = new LinkedHashMap<>();
|
|
||||||
public final ValueVariable[] captures;
|
public final ValueVariable[] captures;
|
||||||
public Environment environment;
|
public FunctionContext environment;
|
||||||
|
|
||||||
public Location loc() {
|
public Location loc() {
|
||||||
for (var instr : body) {
|
for (var instr : body) {
|
||||||
@ -33,24 +28,16 @@ public class CodeFunction extends FunctionValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object call(CallContext ctx, Object thisArg, Object... args) throws InterruptedException {
|
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
|
||||||
return new CodeFrame(ctx, thisArg, args, this).run(new CallContext(ctx, environment));
|
return new CodeFrame(ctx, thisArg, args, this).run(new Context(environment, ctx.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CodeFunction(String name, int localsN, int length, Environment environment, ValueVariable[] captures, Instruction[] body) {
|
public CodeFunction(FunctionContext environment, String name, int localsN, int length, ValueVariable[] captures, Instruction[] body) {
|
||||||
super(name, length);
|
super(name, length);
|
||||||
this.captures = captures;
|
this.captures = captures;
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
this.localsN = localsN;
|
this.localsN = localsN;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
|
|
||||||
for (var i = 0; i < body.length; i++) {
|
|
||||||
if (body[i].type == Type.LOAD_FUNC) i += (int)body[i].get(0);
|
|
||||||
if (body[i].debugged && body[i].location != null) {
|
|
||||||
breakableLocToIndex.put(body[i].location, i);
|
|
||||||
breakableIndexToLoc.put(i, body[i].location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ package me.topchetoeu.jscript.engine.values;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
|
|
||||||
public abstract class FunctionValue extends ObjectValue {
|
public abstract class FunctionValue extends ObjectValue {
|
||||||
public String name = "";
|
public String name = "";
|
||||||
@ -11,29 +11,29 @@ public abstract class FunctionValue extends ObjectValue {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "function(...) { ... }";
|
return "function(...) { ...}";
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Object call(CallContext ctx, Object thisArg, Object... args) throws InterruptedException;
|
public abstract Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException;
|
||||||
public Object call(CallContext ctx) throws InterruptedException {
|
public Object call(Context ctx) throws InterruptedException {
|
||||||
return call(ctx, null);
|
return call(ctx, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object getField(CallContext ctx, Object key) throws InterruptedException {
|
protected Object getField(Context ctx, Object key) throws InterruptedException {
|
||||||
if (key.equals("name")) return name;
|
if (key.equals("name")) return name;
|
||||||
if (key.equals("length")) return length;
|
if (key.equals("length")) return length;
|
||||||
return super.getField(ctx, key);
|
return super.getField(ctx, key);
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected boolean setField(CallContext ctx, Object key, Object val) throws InterruptedException {
|
protected boolean setField(Context ctx, Object key, Object val) throws InterruptedException {
|
||||||
if (key.equals("name")) name = Values.toString(ctx, val);
|
if (key.equals("name")) name = Values.toString(ctx, val);
|
||||||
else if (key.equals("length")) length = (int)Values.toNumber(ctx, val);
|
else if (key.equals("length")) length = (int)Values.toNumber(ctx, val);
|
||||||
else return super.setField(ctx, key, val);
|
else return super.setField(ctx, key, val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
protected boolean hasField(CallContext ctx, Object key) throws InterruptedException {
|
protected boolean hasField(Context ctx, Object key) throws InterruptedException {
|
||||||
if (key.equals("name")) return true;
|
if (key.equals("name")) return true;
|
||||||
if (key.equals("length")) return true;
|
if (key.equals("length")) return true;
|
||||||
return super.hasField(ctx, key);
|
return super.hasField(ctx, key);
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package me.topchetoeu.jscript.engine.values;
|
package me.topchetoeu.jscript.engine.values;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
|
|
||||||
public class NativeFunction extends FunctionValue {
|
public class NativeFunction extends FunctionValue {
|
||||||
public static interface NativeFunctionRunner {
|
public static interface NativeFunctionRunner {
|
||||||
Object run(CallContext ctx, Object thisArg, Object[] args) throws InterruptedException;
|
Object run(Context ctx, Object thisArg, Object[] args) throws InterruptedException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final NativeFunctionRunner action;
|
public final NativeFunctionRunner action;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object call(CallContext ctx, Object thisArg, Object... args) throws InterruptedException {
|
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
|
||||||
return action.run(ctx, thisArg, args);
|
return action.run(ctx, thisArg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package me.topchetoeu.jscript.engine.values;
|
package me.topchetoeu.jscript.engine.values;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
|
|
||||||
public class NativeWrapper extends ObjectValue {
|
public class NativeWrapper extends ObjectValue {
|
||||||
private static final Object NATIVE_PROTO = new Object();
|
private static final Object NATIVE_PROTO = new Object();
|
||||||
public final Object wrapped;
|
public final Object wrapped;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ObjectValue getPrototype(CallContext ctx) throws InterruptedException {
|
public ObjectValue getPrototype(Context ctx) throws InterruptedException {
|
||||||
if (prototype == NATIVE_PROTO) return ctx.environment.wrappersProvider.getProto(wrapped.getClass());
|
if (prototype == NATIVE_PROTO) return ctx.function.wrappersProvider.getProto(wrapped.getClass());
|
||||||
else return super.getPrototype(ctx);
|
else return super.getPrototype(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
|
|
||||||
public class ObjectValue {
|
public class ObjectValue {
|
||||||
public static enum PlaceholderProto {
|
public static enum PlaceholderProto {
|
||||||
@ -78,7 +78,7 @@ public class ObjectValue {
|
|||||||
state = State.FROZEN;
|
state = State.FROZEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean defineProperty(CallContext ctx, Object key, Object val, boolean writable, boolean configurable, boolean enumerable) {
|
public final boolean defineProperty(Context ctx, Object key, Object val, boolean writable, boolean configurable, boolean enumerable) {
|
||||||
key = Values.normalize(ctx, key); val = Values.normalize(ctx, val);
|
key = Values.normalize(ctx, key); val = Values.normalize(ctx, val);
|
||||||
boolean reconfigured =
|
boolean reconfigured =
|
||||||
writable != memberWritable(key) ||
|
writable != memberWritable(key) ||
|
||||||
@ -118,10 +118,10 @@ public class ObjectValue {
|
|||||||
values.put(key, val);
|
values.put(key, val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public final boolean defineProperty(CallContext ctx, Object key, Object val) {
|
public final boolean defineProperty(Context ctx, Object key, Object val) {
|
||||||
return defineProperty(ctx, key, val, true, true, true);
|
return defineProperty(ctx, key, val, true, true, true);
|
||||||
}
|
}
|
||||||
public final boolean defineProperty(CallContext ctx, Object key, FunctionValue getter, FunctionValue setter, boolean configurable, boolean enumerable) {
|
public final boolean defineProperty(Context ctx, Object key, FunctionValue getter, FunctionValue setter, boolean configurable, boolean enumerable) {
|
||||||
key = Values.normalize(ctx, key);
|
key = Values.normalize(ctx, key);
|
||||||
if (
|
if (
|
||||||
properties.containsKey(key) &&
|
properties.containsKey(key) &&
|
||||||
@ -145,15 +145,15 @@ public class ObjectValue {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectValue getPrototype(CallContext ctx) throws InterruptedException {
|
public ObjectValue getPrototype(Context ctx) throws InterruptedException {
|
||||||
try {
|
try {
|
||||||
if (prototype == OBJ_PROTO) return ctx.environment.proto("object");
|
if (prototype == OBJ_PROTO) return ctx.function.proto("object");
|
||||||
if (prototype == ARR_PROTO) return ctx.environment.proto("array");
|
if (prototype == ARR_PROTO) return ctx.function.proto("array");
|
||||||
if (prototype == FUNC_PROTO) return ctx.environment.proto("function");
|
if (prototype == FUNC_PROTO) return ctx.function.proto("function");
|
||||||
if (prototype == ERR_PROTO) return ctx.environment.proto("error");
|
if (prototype == ERR_PROTO) return ctx.function.proto("error");
|
||||||
if (prototype == RANGE_ERR_PROTO) return ctx.environment.proto("rangeErr");
|
if (prototype == RANGE_ERR_PROTO) return ctx.function.proto("rangeErr");
|
||||||
if (prototype == SYNTAX_ERR_PROTO) return ctx.environment.proto("syntaxErr");
|
if (prototype == SYNTAX_ERR_PROTO) return ctx.function.proto("syntaxErr");
|
||||||
if (prototype == TYPE_ERR_PROTO) return ctx.environment.proto("typeErr");
|
if (prototype == TYPE_ERR_PROTO) return ctx.function.proto("typeErr");
|
||||||
}
|
}
|
||||||
catch (NullPointerException e) {
|
catch (NullPointerException e) {
|
||||||
return null;
|
return null;
|
||||||
@ -161,7 +161,7 @@ public class ObjectValue {
|
|||||||
|
|
||||||
return (ObjectValue)prototype;
|
return (ObjectValue)prototype;
|
||||||
}
|
}
|
||||||
public final boolean setPrototype(CallContext ctx, Object val) {
|
public final boolean setPrototype(Context ctx, Object val) {
|
||||||
val = Values.normalize(ctx, val);
|
val = Values.normalize(ctx, val);
|
||||||
|
|
||||||
if (!extensible()) return false;
|
if (!extensible()) return false;
|
||||||
@ -172,14 +172,14 @@ public class ObjectValue {
|
|||||||
else if (Values.isObject(val)) {
|
else if (Values.isObject(val)) {
|
||||||
var obj = Values.object(val);
|
var obj = Values.object(val);
|
||||||
|
|
||||||
if (ctx != null && ctx.environment != null) {
|
if (ctx != null && ctx.function != null) {
|
||||||
if (obj == ctx.environment.proto("object")) prototype = OBJ_PROTO;
|
if (obj == ctx.function.proto("object")) prototype = OBJ_PROTO;
|
||||||
else if (obj == ctx.environment.proto("array")) prototype = ARR_PROTO;
|
else if (obj == ctx.function.proto("array")) prototype = ARR_PROTO;
|
||||||
else if (obj == ctx.environment.proto("function")) prototype = FUNC_PROTO;
|
else if (obj == ctx.function.proto("function")) prototype = FUNC_PROTO;
|
||||||
else if (obj == ctx.environment.proto("error")) prototype = ERR_PROTO;
|
else if (obj == ctx.function.proto("error")) prototype = ERR_PROTO;
|
||||||
else if (obj == ctx.environment.proto("syntaxErr")) prototype = SYNTAX_ERR_PROTO;
|
else if (obj == ctx.function.proto("syntaxErr")) prototype = SYNTAX_ERR_PROTO;
|
||||||
else if (obj == ctx.environment.proto("typeErr")) prototype = TYPE_ERR_PROTO;
|
else if (obj == ctx.function.proto("typeErr")) prototype = TYPE_ERR_PROTO;
|
||||||
else if (obj == ctx.environment.proto("rangeErr")) prototype = RANGE_ERR_PROTO;
|
else if (obj == ctx.function.proto("rangeErr")) prototype = RANGE_ERR_PROTO;
|
||||||
else prototype = obj;
|
else prototype = obj;
|
||||||
}
|
}
|
||||||
else prototype = obj;
|
else prototype = obj;
|
||||||
@ -203,19 +203,19 @@ public class ObjectValue {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Property getProperty(CallContext ctx, Object key) throws InterruptedException {
|
protected Property getProperty(Context ctx, Object key) throws InterruptedException {
|
||||||
if (properties.containsKey(key)) return properties.get(key);
|
if (properties.containsKey(key)) return properties.get(key);
|
||||||
var proto = getPrototype(ctx);
|
var proto = getPrototype(ctx);
|
||||||
if (proto != null) return proto.getProperty(ctx, key);
|
if (proto != null) return proto.getProperty(ctx, key);
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
protected Object getField(CallContext ctx, Object key) throws InterruptedException {
|
protected Object getField(Context ctx, Object key) throws InterruptedException {
|
||||||
if (values.containsKey(key)) return values.get(key);
|
if (values.containsKey(key)) return values.get(key);
|
||||||
var proto = getPrototype(ctx);
|
var proto = getPrototype(ctx);
|
||||||
if (proto != null) return proto.getField(ctx, key);
|
if (proto != null) return proto.getField(ctx, key);
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
protected boolean setField(CallContext ctx, Object key, Object val) throws InterruptedException {
|
protected boolean setField(Context ctx, Object key, Object val) throws InterruptedException {
|
||||||
if (val instanceof FunctionValue && ((FunctionValue)val).name.equals("")) {
|
if (val instanceof FunctionValue && ((FunctionValue)val).name.equals("")) {
|
||||||
((FunctionValue)val).name = Values.toString(ctx, key);
|
((FunctionValue)val).name = Values.toString(ctx, key);
|
||||||
}
|
}
|
||||||
@ -223,14 +223,14 @@ public class ObjectValue {
|
|||||||
values.put(key, val);
|
values.put(key, val);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
protected void deleteField(CallContext ctx, Object key) throws InterruptedException {
|
protected void deleteField(Context ctx, Object key) throws InterruptedException {
|
||||||
values.remove(key);
|
values.remove(key);
|
||||||
}
|
}
|
||||||
protected boolean hasField(CallContext ctx, Object key) throws InterruptedException {
|
protected boolean hasField(Context ctx, Object key) throws InterruptedException {
|
||||||
return values.containsKey(key);
|
return values.containsKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final Object getMember(CallContext ctx, Object key, Object thisArg) throws InterruptedException {
|
public final Object getMember(Context ctx, Object key, Object thisArg) throws InterruptedException {
|
||||||
key = Values.normalize(ctx, key);
|
key = Values.normalize(ctx, key);
|
||||||
|
|
||||||
if (key.equals("__proto__")) {
|
if (key.equals("__proto__")) {
|
||||||
@ -246,11 +246,11 @@ public class ObjectValue {
|
|||||||
}
|
}
|
||||||
else return getField(ctx, key);
|
else return getField(ctx, key);
|
||||||
}
|
}
|
||||||
public final Object getMember(CallContext ctx, Object key) throws InterruptedException {
|
public final Object getMember(Context ctx, Object key) throws InterruptedException {
|
||||||
return getMember(ctx, key, this);
|
return getMember(ctx, key, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean setMember(CallContext ctx, Object key, Object val, Object thisArg, boolean onlyProps) throws InterruptedException {
|
public final boolean setMember(Context ctx, Object key, Object val, Object thisArg, boolean onlyProps) throws InterruptedException {
|
||||||
key = Values.normalize(ctx, key); val = Values.normalize(ctx, val);
|
key = Values.normalize(ctx, key); val = Values.normalize(ctx, val);
|
||||||
|
|
||||||
var prop = getProperty(ctx, key);
|
var prop = getProperty(ctx, key);
|
||||||
@ -269,11 +269,11 @@ public class ObjectValue {
|
|||||||
else if (nonWritableSet.contains(key)) return false;
|
else if (nonWritableSet.contains(key)) return false;
|
||||||
else return setField(ctx, key, val);
|
else return setField(ctx, key, val);
|
||||||
}
|
}
|
||||||
public final boolean setMember(CallContext ctx, Object key, Object val, boolean onlyProps) throws InterruptedException {
|
public final boolean setMember(Context ctx, Object key, Object val, boolean onlyProps) throws InterruptedException {
|
||||||
return setMember(ctx, Values.normalize(ctx, key), Values.normalize(ctx, val), this, onlyProps);
|
return setMember(ctx, Values.normalize(ctx, key), Values.normalize(ctx, val), this, onlyProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final boolean hasMember(CallContext ctx, Object key, boolean own) throws InterruptedException {
|
public final boolean hasMember(Context ctx, Object key, boolean own) throws InterruptedException {
|
||||||
key = Values.normalize(ctx, key);
|
key = Values.normalize(ctx, key);
|
||||||
|
|
||||||
if (key != null && key.equals("__proto__")) return true;
|
if (key != null && key.equals("__proto__")) return true;
|
||||||
@ -283,7 +283,7 @@ public class ObjectValue {
|
|||||||
var proto = getPrototype(ctx);
|
var proto = getPrototype(ctx);
|
||||||
return proto != null && proto.hasMember(ctx, key, own);
|
return proto != null && proto.hasMember(ctx, key, own);
|
||||||
}
|
}
|
||||||
public final boolean deleteMember(CallContext ctx, Object key) throws InterruptedException {
|
public final boolean deleteMember(Context ctx, Object key) throws InterruptedException {
|
||||||
key = Values.normalize(ctx, key);
|
key = Values.normalize(ctx, key);
|
||||||
|
|
||||||
if (!memberConfigurable(key)) return false;
|
if (!memberConfigurable(key)) return false;
|
||||||
@ -294,7 +294,7 @@ public class ObjectValue {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final ObjectValue getMemberDescriptor(CallContext ctx, Object key) throws InterruptedException {
|
public final ObjectValue getMemberDescriptor(Context ctx, Object key) throws InterruptedException {
|
||||||
key = Values.normalize(ctx, key);
|
key = Values.normalize(ctx, key);
|
||||||
|
|
||||||
var prop = properties.get(key);
|
var prop = properties.get(key);
|
||||||
@ -330,7 +330,7 @@ public class ObjectValue {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ObjectValue(CallContext ctx, Map<?, ?> values) {
|
public ObjectValue(Context ctx, Map<?, ?> values) {
|
||||||
this(PlaceholderProto.OBJECT);
|
this(PlaceholderProto.OBJECT);
|
||||||
for (var el : values.entrySet()) {
|
for (var el : values.entrySet()) {
|
||||||
defineProperty(ctx, el.getKey(), el.getValue());
|
defineProperty(ctx, el.getKey(), el.getValue());
|
||||||
|
@ -10,7 +10,7 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.Operation;
|
import me.topchetoeu.jscript.engine.Operation;
|
||||||
import me.topchetoeu.jscript.engine.frame.ConvertHint;
|
import me.topchetoeu.jscript.engine.frame.ConvertHint;
|
||||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||||
@ -65,7 +65,7 @@ public class Values {
|
|||||||
return "object";
|
return "object";
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object tryCallConvertFunc(CallContext ctx, Object obj, String name) throws InterruptedException {
|
private static Object tryCallConvertFunc(Context ctx, Object obj, String name) throws InterruptedException {
|
||||||
var func = getMember(ctx, obj, name);
|
var func = getMember(ctx, obj, name);
|
||||||
|
|
||||||
if (func != null) {
|
if (func != null) {
|
||||||
@ -87,7 +87,7 @@ public class Values {
|
|||||||
obj == NULL;
|
obj == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object toPrimitive(CallContext ctx, Object obj, ConvertHint hint) throws InterruptedException {
|
public static Object toPrimitive(Context ctx, Object obj, ConvertHint hint) throws InterruptedException {
|
||||||
obj = normalize(ctx, obj);
|
obj = normalize(ctx, obj);
|
||||||
if (isPrimitive(obj)) return obj;
|
if (isPrimitive(obj)) return obj;
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ public class Values {
|
|||||||
if (obj instanceof Boolean) return (Boolean)obj;
|
if (obj instanceof Boolean) return (Boolean)obj;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
public static double toNumber(CallContext ctx, Object obj) throws InterruptedException {
|
public static double toNumber(Context ctx, Object obj) throws InterruptedException {
|
||||||
var val = toPrimitive(ctx, obj, ConvertHint.VALUEOF);
|
var val = toPrimitive(ctx, obj, ConvertHint.VALUEOF);
|
||||||
|
|
||||||
if (val instanceof Number) return number(obj);
|
if (val instanceof Number) return number(obj);
|
||||||
@ -125,7 +125,7 @@ public class Values {
|
|||||||
}
|
}
|
||||||
return Double.NaN;
|
return Double.NaN;
|
||||||
}
|
}
|
||||||
public static String toString(CallContext ctx, Object obj) throws InterruptedException {
|
public static String toString(Context ctx, Object obj) throws InterruptedException {
|
||||||
var val = toPrimitive(ctx, obj, ConvertHint.VALUEOF);
|
var val = toPrimitive(ctx, obj, ConvertHint.VALUEOF);
|
||||||
|
|
||||||
if (val == null) return "undefined";
|
if (val == null) return "undefined";
|
||||||
@ -146,47 +146,47 @@ public class Values {
|
|||||||
return "Unknown value";
|
return "Unknown value";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object add(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static Object add(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
if (a instanceof String || b instanceof String) return toString(ctx, a) + toString(ctx, b);
|
if (a instanceof String || b instanceof String) return toString(ctx, a) + toString(ctx, b);
|
||||||
else return toNumber(ctx, a) + toNumber(ctx, b);
|
else return toNumber(ctx, a) + toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static double subtract(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static double subtract(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return toNumber(ctx, a) - toNumber(ctx, b);
|
return toNumber(ctx, a) - toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static double multiply(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static double multiply(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return toNumber(ctx, a) * toNumber(ctx, b);
|
return toNumber(ctx, a) * toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static double divide(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static double divide(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return toNumber(ctx, a) / toNumber(ctx, b);
|
return toNumber(ctx, a) / toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static double modulo(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static double modulo(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return toNumber(ctx, a) % toNumber(ctx, b);
|
return toNumber(ctx, a) % toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static double negative(CallContext ctx, Object obj) throws InterruptedException {
|
public static double negative(Context ctx, Object obj) throws InterruptedException {
|
||||||
return -toNumber(ctx, obj);
|
return -toNumber(ctx, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int and(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static int and(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return (int)toNumber(ctx, a) & (int)toNumber(ctx, b);
|
return (int)toNumber(ctx, a) & (int)toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static int or(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static int or(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return (int)toNumber(ctx, a) | (int)toNumber(ctx, b);
|
return (int)toNumber(ctx, a) | (int)toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static int xor(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static int xor(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return (int)toNumber(ctx, a) ^ (int)toNumber(ctx, b);
|
return (int)toNumber(ctx, a) ^ (int)toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static int bitwiseNot(CallContext ctx, Object obj) throws InterruptedException {
|
public static int bitwiseNot(Context ctx, Object obj) throws InterruptedException {
|
||||||
return ~(int)toNumber(ctx, obj);
|
return ~(int)toNumber(ctx, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int shiftLeft(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static int shiftLeft(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return (int)toNumber(ctx, a) << (int)toNumber(ctx, b);
|
return (int)toNumber(ctx, a) << (int)toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static int shiftRight(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static int shiftRight(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
return (int)toNumber(ctx, a) >> (int)toNumber(ctx, b);
|
return (int)toNumber(ctx, a) >> (int)toNumber(ctx, b);
|
||||||
}
|
}
|
||||||
public static long unsignedShiftRight(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static long unsignedShiftRight(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
long _a = (long)toNumber(ctx, a);
|
long _a = (long)toNumber(ctx, a);
|
||||||
long _b = (long)toNumber(ctx, b);
|
long _b = (long)toNumber(ctx, b);
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ public class Values {
|
|||||||
return _a >>> _b;
|
return _a >>> _b;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int compare(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static int compare(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
a = toPrimitive(ctx, a, ConvertHint.VALUEOF);
|
a = toPrimitive(ctx, a, ConvertHint.VALUEOF);
|
||||||
b = toPrimitive(ctx, b, ConvertHint.VALUEOF);
|
b = toPrimitive(ctx, b, ConvertHint.VALUEOF);
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ public class Values {
|
|||||||
return !toBoolean(obj);
|
return !toBoolean(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isInstanceOf(CallContext ctx, Object obj, Object proto) throws InterruptedException {
|
public static boolean isInstanceOf(Context ctx, Object obj, Object proto) throws InterruptedException {
|
||||||
if (obj == null || obj == NULL || proto == null || proto == NULL) return false;
|
if (obj == null || obj == NULL || proto == null || proto == NULL) return false;
|
||||||
var val = getPrototype(ctx, obj);
|
var val = getPrototype(ctx, obj);
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ public class Values {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object operation(CallContext ctx, Operation op, Object... args) throws InterruptedException {
|
public static Object operation(Context ctx, Operation op, Object ...args) throws InterruptedException {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case ADD: return add(ctx, args[0], args[1]);
|
case ADD: return add(ctx, args[0], args[1]);
|
||||||
case SUBTRACT: return subtract(ctx, args[0], args[1]);
|
case SUBTRACT: return subtract(ctx, args[0], args[1]);
|
||||||
@ -260,7 +260,7 @@ public class Values {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object getMember(CallContext ctx, Object obj, Object key) throws InterruptedException {
|
public static Object getMember(Context ctx, Object obj, Object key) throws InterruptedException {
|
||||||
obj = normalize(ctx, obj); key = normalize(ctx, key);
|
obj = normalize(ctx, obj); key = normalize(ctx, key);
|
||||||
if (obj == null) throw new IllegalArgumentException("Tried to access member of undefined.");
|
if (obj == null) throw new IllegalArgumentException("Tried to access member of undefined.");
|
||||||
if (obj == NULL) throw new IllegalArgumentException("Tried to access member of null.");
|
if (obj == NULL) throw new IllegalArgumentException("Tried to access member of null.");
|
||||||
@ -280,7 +280,7 @@ public class Values {
|
|||||||
else if (key != null && key.equals("__proto__")) return proto;
|
else if (key != null && key.equals("__proto__")) return proto;
|
||||||
else return proto.getMember(ctx, key, obj);
|
else return proto.getMember(ctx, key, obj);
|
||||||
}
|
}
|
||||||
public static boolean setMember(CallContext ctx, Object obj, Object key, Object val) throws InterruptedException {
|
public static boolean setMember(Context ctx, Object obj, Object key, Object val) throws InterruptedException {
|
||||||
obj = normalize(ctx, obj); key = normalize(ctx, key); val = normalize(ctx, val);
|
obj = normalize(ctx, obj); key = normalize(ctx, key); val = normalize(ctx, val);
|
||||||
if (obj == null) throw EngineException.ofType("Tried to access member of undefined.");
|
if (obj == null) throw EngineException.ofType("Tried to access member of undefined.");
|
||||||
if (obj == NULL) throw EngineException.ofType("Tried to access member of null.");
|
if (obj == NULL) throw EngineException.ofType("Tried to access member of null.");
|
||||||
@ -290,7 +290,7 @@ public class Values {
|
|||||||
var proto = getPrototype(ctx, obj);
|
var proto = getPrototype(ctx, obj);
|
||||||
return proto.setMember(ctx, key, val, obj, true);
|
return proto.setMember(ctx, key, val, obj, true);
|
||||||
}
|
}
|
||||||
public static boolean hasMember(CallContext ctx, Object obj, Object key, boolean own) throws InterruptedException {
|
public static boolean hasMember(Context ctx, Object obj, Object key, boolean own) throws InterruptedException {
|
||||||
if (obj == null || obj == NULL) return false;
|
if (obj == null || obj == NULL) return false;
|
||||||
obj = normalize(ctx, obj); key = normalize(ctx, key);
|
obj = normalize(ctx, obj); key = normalize(ctx, key);
|
||||||
|
|
||||||
@ -308,31 +308,31 @@ public class Values {
|
|||||||
var proto = getPrototype(ctx, obj);
|
var proto = getPrototype(ctx, obj);
|
||||||
return proto != null && proto.hasMember(ctx, key, own);
|
return proto != null && proto.hasMember(ctx, key, own);
|
||||||
}
|
}
|
||||||
public static boolean deleteMember(CallContext ctx, Object obj, Object key) throws InterruptedException {
|
public static boolean deleteMember(Context ctx, Object obj, Object key) throws InterruptedException {
|
||||||
if (obj == null || obj == NULL) return false;
|
if (obj == null || obj == NULL) return false;
|
||||||
obj = normalize(ctx, obj); key = normalize(ctx, key);
|
obj = normalize(ctx, obj); key = normalize(ctx, key);
|
||||||
|
|
||||||
if (isObject(obj)) return object(obj).deleteMember(ctx, key);
|
if (isObject(obj)) return object(obj).deleteMember(ctx, key);
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
public static ObjectValue getPrototype(CallContext ctx, Object obj) throws InterruptedException {
|
public static ObjectValue getPrototype(Context ctx, Object obj) throws InterruptedException {
|
||||||
if (obj == null || obj == NULL) return null;
|
if (obj == null || obj == NULL) return null;
|
||||||
obj = normalize(ctx, obj);
|
obj = normalize(ctx, obj);
|
||||||
if (isObject(obj)) return object(obj).getPrototype(ctx);
|
if (isObject(obj)) return object(obj).getPrototype(ctx);
|
||||||
if (ctx == null) return null;
|
if (ctx == null) return null;
|
||||||
|
|
||||||
if (obj instanceof String) return ctx.environment.proto("string");
|
if (obj instanceof String) return ctx.function.proto("string");
|
||||||
else if (obj instanceof Number) return ctx.environment.proto("number");
|
else if (obj instanceof Number) return ctx.function.proto("number");
|
||||||
else if (obj instanceof Boolean) return ctx.environment.proto("bool");
|
else if (obj instanceof Boolean) return ctx.function.proto("bool");
|
||||||
else if (obj instanceof Symbol) return ctx.environment.proto("symbol");
|
else if (obj instanceof Symbol) return ctx.function.proto("symbol");
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public static boolean setPrototype(CallContext ctx, Object obj, Object proto) throws InterruptedException {
|
public static boolean setPrototype(Context ctx, Object obj, Object proto) throws InterruptedException {
|
||||||
obj = normalize(ctx, obj);
|
obj = normalize(ctx, obj);
|
||||||
return isObject(obj) && object(obj).setPrototype(ctx, proto);
|
return isObject(obj) && object(obj).setPrototype(ctx, proto);
|
||||||
}
|
}
|
||||||
public static List<Object> getMembers(CallContext ctx, Object obj, boolean own, boolean includeNonEnumerable) throws InterruptedException {
|
public static List<Object> getMembers(Context ctx, Object obj, boolean own, boolean includeNonEnumerable) throws InterruptedException {
|
||||||
List<Object> res = new ArrayList<>();
|
List<Object> res = new ArrayList<>();
|
||||||
|
|
||||||
if (isObject(obj)) res = object(obj).keys(includeNonEnumerable);
|
if (isObject(obj)) res = object(obj).keys(includeNonEnumerable);
|
||||||
@ -353,13 +353,13 @@ public class Values {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object call(CallContext ctx, Object func, Object thisArg, Object ...args) throws InterruptedException {
|
public static Object call(Context ctx, Object func, Object thisArg, Object ...args) throws InterruptedException {
|
||||||
if (!isFunction(func))
|
if (!isFunction(func))
|
||||||
throw EngineException.ofType("Tried to call a non-function value.");
|
throw EngineException.ofType("Tried to call a non-function value.");
|
||||||
return function(func).call(ctx, thisArg, args);
|
return function(func).call(ctx, thisArg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean strictEquals(CallContext ctx, Object a, Object b) {
|
public static boolean strictEquals(Context ctx, Object a, Object b) {
|
||||||
a = normalize(ctx, a); b = normalize(ctx, b);
|
a = normalize(ctx, a); b = normalize(ctx, b);
|
||||||
|
|
||||||
if (a == null || b == null) return a == null && b == null;
|
if (a == null || b == null) return a == null && b == null;
|
||||||
@ -369,7 +369,7 @@ public class Values {
|
|||||||
|
|
||||||
return a == b || a.equals(b);
|
return a == b || a.equals(b);
|
||||||
}
|
}
|
||||||
public static boolean looseEqual(CallContext ctx, Object a, Object b) throws InterruptedException {
|
public static boolean looseEqual(Context ctx, Object a, Object b) throws InterruptedException {
|
||||||
a = normalize(ctx, a); b = normalize(ctx, b);
|
a = normalize(ctx, a); b = normalize(ctx, b);
|
||||||
|
|
||||||
// In loose equality, null is equivalent to undefined
|
// In loose equality, null is equivalent to undefined
|
||||||
@ -393,7 +393,7 @@ public class Values {
|
|||||||
return toString(ctx, a).equals(toString(ctx, b));
|
return toString(ctx, a).equals(toString(ctx, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Object normalize(CallContext ctx, Object val) {
|
public static Object normalize(Context ctx, Object val) {
|
||||||
if (val instanceof Number) return number(val);
|
if (val instanceof Number) return number(val);
|
||||||
if (isPrimitive(val) || val instanceof ObjectValue) return val;
|
if (isPrimitive(val) || val instanceof ObjectValue) return val;
|
||||||
if (val instanceof Character) return val + "";
|
if (val instanceof Character) return val + "";
|
||||||
@ -420,14 +420,14 @@ public class Values {
|
|||||||
|
|
||||||
if (val instanceof Class) {
|
if (val instanceof Class) {
|
||||||
if (ctx == null) return null;
|
if (ctx == null) return null;
|
||||||
else return ctx.environment.wrappersProvider.getConstr((Class<?>)val);
|
else return ctx.function.wrappersProvider.getConstr((Class<?>)val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new NativeWrapper(val);
|
return new NativeWrapper(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <T> T convert(CallContext ctx, Object obj, Class<T> clazz) throws InterruptedException {
|
public static <T> T convert(Context ctx, Object obj, Class<T> clazz) throws InterruptedException {
|
||||||
if (clazz == Void.class) return null;
|
if (clazz == Void.class) return null;
|
||||||
if (clazz == null || clazz == Object.class) return (T)obj;
|
if (clazz == null || clazz == Object.class) return (T)obj;
|
||||||
|
|
||||||
@ -495,10 +495,10 @@ public class Values {
|
|||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Iterable<Object> toJavaIterable(CallContext ctx, Object obj) throws InterruptedException {
|
public static Iterable<Object> toJavaIterable(Context ctx, Object obj) throws InterruptedException {
|
||||||
return () -> {
|
return () -> {
|
||||||
try {
|
try {
|
||||||
var constr = getMember(ctx, ctx.environment.proto("symbol"), "constructor");
|
var constr = getMember(ctx, ctx.function.proto("symbol"), "constructor");
|
||||||
var symbol = getMember(ctx, constr, "iterator");
|
var symbol = getMember(ctx, constr, "iterator");
|
||||||
|
|
||||||
var iteratorFunc = getMember(ctx, obj, symbol);
|
var iteratorFunc = getMember(ctx, obj, symbol);
|
||||||
@ -562,12 +562,12 @@ public class Values {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ObjectValue fromJavaIterable(CallContext ctx, Iterable<?> iterable) throws InterruptedException {
|
public static ObjectValue fromJavaIterable(Context ctx, Iterable<?> iterable) throws InterruptedException {
|
||||||
var res = new ObjectValue();
|
var res = new ObjectValue();
|
||||||
var it = iterable.iterator();
|
var it = iterable.iterator();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var key = getMember(ctx, getMember(ctx, ctx.environment.proto("symbol"), "constructor"), "iterator");
|
var key = getMember(ctx, getMember(ctx, ctx.function.proto("symbol"), "constructor"), "iterator");
|
||||||
res.defineProperty(ctx, key, new NativeFunction("", (_ctx, thisArg, args) -> thisArg));
|
res.defineProperty(ctx, key, new NativeFunction("", (_ctx, thisArg, args) -> thisArg));
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException | NullPointerException e) { }
|
catch (IllegalArgumentException | NullPointerException e) { }
|
||||||
@ -580,7 +580,7 @@ public class Values {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printValue(CallContext ctx, Object val, HashSet<Object> passed, int tab) throws InterruptedException {
|
private static void printValue(Context ctx, Object val, HashSet<Object> passed, int tab) throws InterruptedException {
|
||||||
if (passed.contains(val)) {
|
if (passed.contains(val)) {
|
||||||
System.out.print("[circular]");
|
System.out.print("[circular]");
|
||||||
return;
|
return;
|
||||||
@ -652,7 +652,7 @@ public class Values {
|
|||||||
else if (val instanceof String) System.out.print("'" + val + "'");
|
else if (val instanceof String) System.out.print("'" + val + "'");
|
||||||
else System.out.print(Values.toString(ctx, val));
|
else System.out.print(Values.toString(ctx, val));
|
||||||
}
|
}
|
||||||
public static void printValue(CallContext ctx, Object val) throws InterruptedException {
|
public static void printValue(Context ctx, Object val) throws InterruptedException {
|
||||||
printValue(ctx, val, new HashSet<>(), 0);
|
printValue(ctx, val, new HashSet<>(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.Location;
|
import me.topchetoeu.jscript.Location;
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
import me.topchetoeu.jscript.engine.values.Values;
|
||||||
import me.topchetoeu.jscript.engine.values.ObjectValue.PlaceholderProto;
|
import me.topchetoeu.jscript.engine.values.ObjectValue.PlaceholderProto;
|
||||||
@ -28,9 +28,14 @@ public class EngineException extends RuntimeException {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString(CallContext ctx) throws InterruptedException {
|
public String toString(Context ctx) throws InterruptedException {
|
||||||
var ss = new StringBuilder();
|
var ss = new StringBuilder();
|
||||||
ss.append(Values.toString(ctx, value)).append('\n');
|
try {
|
||||||
|
ss.append(Values.toString(ctx, value)).append('\n');
|
||||||
|
}
|
||||||
|
catch (EngineException e) {
|
||||||
|
ss.append("[Error while stringifying]\n");
|
||||||
|
}
|
||||||
for (var line : stackTrace) {
|
for (var line : stackTrace) {
|
||||||
ss.append(" ").append(line).append('\n');
|
ss.append(" ").append(line).append('\n');
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package me.topchetoeu.jscript.filesystem;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
public class FilesystemRegister {
|
|
||||||
private HashMap<String, Filesystem> filesystems = new HashMap<>();
|
|
||||||
}
|
|
@ -5,11 +5,11 @@ import java.lang.reflect.Field;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
|
|
||||||
public class Overload {
|
public class Overload {
|
||||||
public static interface OverloadRunner {
|
public static interface OverloadRunner {
|
||||||
Object run(CallContext ctx, Object thisArg, Object[] args) throws
|
Object run(Context ctx, Object thisArg, Object[] args) throws
|
||||||
InterruptedException,
|
InterruptedException,
|
||||||
ReflectiveOperationException,
|
ReflectiveOperationException,
|
||||||
IllegalArgumentException;
|
IllegalArgumentException;
|
||||||
|
@ -5,7 +5,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
import me.topchetoeu.jscript.engine.values.Values;
|
||||||
import me.topchetoeu.jscript.exceptions.EngineException;
|
import me.topchetoeu.jscript.exceptions.EngineException;
|
||||||
@ -13,9 +13,9 @@ import me.topchetoeu.jscript.exceptions.EngineException;
|
|||||||
public class OverloadFunction extends FunctionValue {
|
public class OverloadFunction extends FunctionValue {
|
||||||
public final List<Overload> overloads = new ArrayList<>();
|
public final List<Overload> overloads = new ArrayList<>();
|
||||||
|
|
||||||
public Object call(CallContext ctx, Object thisArg, Object... args) throws InterruptedException {
|
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
|
||||||
for (var overload : overloads) {
|
for (var overload : overloads) {
|
||||||
boolean consumesEngine = overload.params.length > 0 && overload.params[0] == CallContext.class;
|
boolean consumesEngine = overload.params.length > 0 && overload.params[0] == Context.class;
|
||||||
int start = consumesEngine ? 1 : 0;
|
int start = consumesEngine ? 1 : 0;
|
||||||
int end = overload.params.length - (overload.variadic ? 1 : 0);
|
int end = overload.params.length - (overload.variadic ? 1 : 0);
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ public class ParseRes<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public static <T> ParseRes<? extends T> any(ParseRes<? extends T>... parsers) {
|
public static <T> ParseRes<? extends T> any(ParseRes<? extends T> ...parsers) {
|
||||||
ParseRes<? extends T> best = null;
|
ParseRes<? extends T> best = null;
|
||||||
ParseRes<? extends T> error = ParseRes.failed();
|
ParseRes<? extends T> error = ParseRes.failed();
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ public class ParseRes<T> {
|
|||||||
else return error;
|
else return error;
|
||||||
}
|
}
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public static <T> ParseRes<? extends T> first(String filename, List<Token> tokens, Map<String, Parser<T>> named, Parser<? extends T>... parsers) {
|
public static <T> ParseRes<? extends T> first(String filename, List<Token> tokens, Map<String, Parser<T>> named, Parser<? extends T> ...parsers) {
|
||||||
ParseRes<? extends T> error = ParseRes.failed();
|
ParseRes<? extends T> error = ParseRes.failed();
|
||||||
|
|
||||||
for (var parser : parsers) {
|
for (var parser : parsers) {
|
||||||
|
@ -13,7 +13,7 @@ import me.topchetoeu.jscript.compilation.VariableDeclareStatement.Pair;
|
|||||||
import me.topchetoeu.jscript.compilation.control.*;
|
import me.topchetoeu.jscript.compilation.control.*;
|
||||||
import me.topchetoeu.jscript.compilation.control.SwitchStatement.SwitchCase;
|
import me.topchetoeu.jscript.compilation.control.SwitchStatement.SwitchCase;
|
||||||
import me.topchetoeu.jscript.compilation.values.*;
|
import me.topchetoeu.jscript.compilation.values.*;
|
||||||
import me.topchetoeu.jscript.engine.Environment;
|
import me.topchetoeu.jscript.engine.FunctionContext;
|
||||||
import me.topchetoeu.jscript.engine.Operation;
|
import me.topchetoeu.jscript.engine.Operation;
|
||||||
import me.topchetoeu.jscript.engine.scope.ValueVariable;
|
import me.topchetoeu.jscript.engine.scope.ValueVariable;
|
||||||
import me.topchetoeu.jscript.engine.values.CodeFunction;
|
import me.topchetoeu.jscript.engine.values.CodeFunction;
|
||||||
@ -1842,7 +1842,7 @@ public class Parsing {
|
|||||||
return list.toArray(Statement[]::new);
|
return list.toArray(Statement[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CodeFunction compile(Environment environment, Statement... statements) {
|
public static CodeFunction compile(FunctionContext environment, Statement ...statements) {
|
||||||
var target = environment.global.globalChild();
|
var target = environment.global.globalChild();
|
||||||
var subscope = target.child();
|
var subscope = target.child();
|
||||||
var res = new ArrayList<Instruction>();
|
var res = new ArrayList<Instruction>();
|
||||||
@ -1870,14 +1870,14 @@ public class Parsing {
|
|||||||
}
|
}
|
||||||
else res.add(Instruction.ret());
|
else res.add(Instruction.ret());
|
||||||
|
|
||||||
return new CodeFunction("", subscope.localsCount(), 0, environment, new ValueVariable[0], res.toArray(Instruction[]::new));
|
return new CodeFunction(environment, "", subscope.localsCount(), 0, new ValueVariable[0], res.toArray(Instruction[]::new));
|
||||||
}
|
}
|
||||||
public static CodeFunction compile(Environment environment, String filename, String raw) {
|
public static CodeFunction compile(FunctionContext environment, String filename, String raw) {
|
||||||
try {
|
try {
|
||||||
return compile(environment, parse(filename, raw));
|
return compile(environment, parse(filename, raw));
|
||||||
}
|
}
|
||||||
catch (SyntaxException e) {
|
catch (SyntaxException e) {
|
||||||
return new CodeFunction(null, 2, 0, environment, new ValueVariable[0], new Instruction[] { Instruction.throwSyntax(e) });
|
return new CodeFunction(environment, null, 2, 0, new ValueVariable[0], new Instruction[] { Instruction.throwSyntax(e) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package me.topchetoeu.jscript.polyfills;
|
|||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
import me.topchetoeu.jscript.engine.values.Values;
|
||||||
import me.topchetoeu.jscript.interop.Native;
|
import me.topchetoeu.jscript.interop.Native;
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ public class Date {
|
|||||||
return normal.get(Calendar.YEAR) - 1900;
|
return normal.get(Calendar.YEAR) - 1900;
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setYear(CallContext ctx, Object val) throws InterruptedException {
|
public double setYear(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (real >= 0 && real <= 99) real = real + 1900;
|
if (real >= 0 && real <= 99) real = real + 1900;
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
@ -139,7 +139,7 @@ public class Date {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public double setFullYear(CallContext ctx, Object val) throws InterruptedException {
|
public double setFullYear(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else normal.set(Calendar.YEAR, (int)real);
|
else normal.set(Calendar.YEAR, (int)real);
|
||||||
@ -147,7 +147,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setMonth(CallContext ctx, Object val) throws InterruptedException {
|
public double setMonth(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else normal.set(Calendar.MONTH, (int)real);
|
else normal.set(Calendar.MONTH, (int)real);
|
||||||
@ -155,7 +155,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setDate(CallContext ctx, Object val) throws InterruptedException {
|
public double setDate(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else normal.set(Calendar.DAY_OF_MONTH, (int)real);
|
else normal.set(Calendar.DAY_OF_MONTH, (int)real);
|
||||||
@ -163,7 +163,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setDay(CallContext ctx, Object val) throws InterruptedException {
|
public double setDay(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else normal.set(Calendar.DAY_OF_WEEK, (int)real);
|
else normal.set(Calendar.DAY_OF_WEEK, (int)real);
|
||||||
@ -171,7 +171,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setHours(CallContext ctx, Object val) throws InterruptedException {
|
public double setHours(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else normal.set(Calendar.HOUR_OF_DAY, (int)real);
|
else normal.set(Calendar.HOUR_OF_DAY, (int)real);
|
||||||
@ -179,7 +179,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setMinutes(CallContext ctx, Object val) throws InterruptedException {
|
public double setMinutes(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else normal.set(Calendar.MINUTE, (int)real);
|
else normal.set(Calendar.MINUTE, (int)real);
|
||||||
@ -187,7 +187,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setSeconds(CallContext ctx, Object val) throws InterruptedException {
|
public double setSeconds(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else normal.set(Calendar.SECOND, (int)real);
|
else normal.set(Calendar.SECOND, (int)real);
|
||||||
@ -195,7 +195,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setMilliseconds(CallContext ctx, Object val) throws InterruptedException {
|
public double setMilliseconds(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else normal.set(Calendar.MILLISECOND, (int)real);
|
else normal.set(Calendar.MILLISECOND, (int)real);
|
||||||
@ -204,7 +204,7 @@ public class Date {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public double setUTCFullYear(CallContext ctx, Object val) throws InterruptedException {
|
public double setUTCFullYear(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else utc.set(Calendar.YEAR, (int)real);
|
else utc.set(Calendar.YEAR, (int)real);
|
||||||
@ -212,7 +212,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setUTCMonth(CallContext ctx, Object val) throws InterruptedException {
|
public double setUTCMonth(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else utc.set(Calendar.MONTH, (int)real);
|
else utc.set(Calendar.MONTH, (int)real);
|
||||||
@ -220,7 +220,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setUTCDate(CallContext ctx, Object val) throws InterruptedException {
|
public double setUTCDate(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else utc.set(Calendar.DAY_OF_MONTH, (int)real);
|
else utc.set(Calendar.DAY_OF_MONTH, (int)real);
|
||||||
@ -228,7 +228,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setUTCDay(CallContext ctx, Object val) throws InterruptedException {
|
public double setUTCDay(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else utc.set(Calendar.DAY_OF_WEEK, (int)real);
|
else utc.set(Calendar.DAY_OF_WEEK, (int)real);
|
||||||
@ -236,7 +236,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setUTCHours(CallContext ctx, Object val) throws InterruptedException {
|
public double setUTCHours(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else utc.set(Calendar.HOUR_OF_DAY, (int)real);
|
else utc.set(Calendar.HOUR_OF_DAY, (int)real);
|
||||||
@ -244,7 +244,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setUTCMinutes(CallContext ctx, Object val) throws InterruptedException {
|
public double setUTCMinutes(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else utc.set(Calendar.MINUTE, (int)real);
|
else utc.set(Calendar.MINUTE, (int)real);
|
||||||
@ -252,7 +252,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setUTCSeconds(CallContext ctx, Object val) throws InterruptedException {
|
public double setUTCSeconds(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else utc.set(Calendar.SECOND, (int)real);
|
else utc.set(Calendar.SECOND, (int)real);
|
||||||
@ -260,7 +260,7 @@ public class Date {
|
|||||||
return getTime();
|
return getTime();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public double setUTCMilliseconds(CallContext ctx, Object val) throws InterruptedException {
|
public double setUTCMilliseconds(Context ctx, Object val) throws InterruptedException {
|
||||||
var real = Values.toNumber(ctx, val);
|
var real = Values.toNumber(ctx, val);
|
||||||
if (Double.isNaN(real)) invalidate();
|
if (Double.isNaN(real)) invalidate();
|
||||||
else utc.set(Calendar.MILLISECOND, (int)real);
|
else utc.set(Calendar.MILLISECOND, (int)real);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.polyfills;
|
package me.topchetoeu.jscript.polyfills;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.frame.CodeFrame;
|
import me.topchetoeu.jscript.engine.frame.CodeFrame;
|
||||||
import me.topchetoeu.jscript.engine.frame.Runners;
|
import me.topchetoeu.jscript.engine.frame.Runners;
|
||||||
import me.topchetoeu.jscript.engine.values.CodeFunction;
|
import me.topchetoeu.jscript.engine.values.CodeFunction;
|
||||||
@ -18,7 +18,7 @@ public class GeneratorFunction extends FunctionValue {
|
|||||||
private boolean done = false;
|
private boolean done = false;
|
||||||
public CodeFrame frame;
|
public CodeFrame frame;
|
||||||
|
|
||||||
private ObjectValue next(CallContext ctx, Object inducedValue, Object inducedReturn, Object inducedError) throws InterruptedException {
|
private ObjectValue next(Context ctx, Object inducedValue, Object inducedReturn, Object inducedError) throws InterruptedException {
|
||||||
if (done) {
|
if (done) {
|
||||||
if (inducedError != Runners.NO_RETURN) throw new EngineException(inducedError);
|
if (inducedError != Runners.NO_RETURN) throw new EngineException(inducedError);
|
||||||
var res = new ObjectValue();
|
var res = new ObjectValue();
|
||||||
@ -29,7 +29,7 @@ public class GeneratorFunction extends FunctionValue {
|
|||||||
|
|
||||||
Object res = null;
|
Object res = null;
|
||||||
if (inducedValue != Runners.NO_RETURN) frame.push(ctx, inducedValue);
|
if (inducedValue != Runners.NO_RETURN) frame.push(ctx, inducedValue);
|
||||||
frame.start(ctx);
|
ctx.message.pushFrame(frame);
|
||||||
yielding = false;
|
yielding = false;
|
||||||
while (!yielding) {
|
while (!yielding) {
|
||||||
try {
|
try {
|
||||||
@ -46,7 +46,7 @@ public class GeneratorFunction extends FunctionValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.end(ctx);
|
ctx.message.popFrame(frame);
|
||||||
if (done) frame = null;
|
if (done) frame = null;
|
||||||
else res = frame.pop();
|
else res = frame.pop();
|
||||||
|
|
||||||
@ -57,16 +57,16 @@ public class GeneratorFunction extends FunctionValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public ObjectValue next(CallContext ctx, Object... args) throws InterruptedException {
|
public ObjectValue next(Context ctx, Object ...args) throws InterruptedException {
|
||||||
if (args.length == 0) return next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, Runners.NO_RETURN);
|
if (args.length == 0) return next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, Runners.NO_RETURN);
|
||||||
else return next(ctx, args[0], Runners.NO_RETURN, Runners.NO_RETURN);
|
else return next(ctx, args[0], Runners.NO_RETURN, Runners.NO_RETURN);
|
||||||
}
|
}
|
||||||
@Native("throw")
|
@Native("throw")
|
||||||
public ObjectValue _throw(CallContext ctx, Object error) throws InterruptedException {
|
public ObjectValue _throw(Context ctx, Object error) throws InterruptedException {
|
||||||
return next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, error);
|
return next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, error);
|
||||||
}
|
}
|
||||||
@Native("return")
|
@Native("return")
|
||||||
public ObjectValue _return(CallContext ctx, Object value) throws InterruptedException {
|
public ObjectValue _return(Context ctx, Object value) throws InterruptedException {
|
||||||
return next(ctx, Runners.NO_RETURN, value, Runners.NO_RETURN);
|
return next(ctx, Runners.NO_RETURN, value, Runners.NO_RETURN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,14 +77,14 @@ public class GeneratorFunction extends FunctionValue {
|
|||||||
return "Generator " + (done ? "[closed]" : "[suspended]");
|
return "Generator " + (done ? "[closed]" : "[suspended]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object yield(CallContext ctx, Object thisArg, Object[] args) {
|
public Object yield(Context ctx, Object thisArg, Object[] args) {
|
||||||
this.yielding = true;
|
this.yielding = true;
|
||||||
return args.length > 0 ? args[0] : null;
|
return args.length > 0 ? args[0] : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object call(CallContext ctx, Object thisArg, Object... args) throws InterruptedException {
|
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
|
||||||
var handler = new Generator();
|
var handler = new Generator();
|
||||||
var func = factory.call(ctx, thisArg, new NativeFunction("yield", handler::yield));
|
var func = factory.call(ctx, thisArg, new NativeFunction("yield", handler::yield));
|
||||||
if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function.");
|
if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function.");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package me.topchetoeu.jscript.polyfills;
|
package me.topchetoeu.jscript.polyfills;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.Environment;
|
import me.topchetoeu.jscript.engine.FunctionContext;
|
||||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||||
import me.topchetoeu.jscript.engine.values.CodeFunction;
|
import me.topchetoeu.jscript.engine.values.CodeFunction;
|
||||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
||||||
@ -12,23 +12,23 @@ import me.topchetoeu.jscript.engine.values.Values;
|
|||||||
import me.topchetoeu.jscript.interop.Native;
|
import me.topchetoeu.jscript.interop.Native;
|
||||||
|
|
||||||
public class Internals {
|
public class Internals {
|
||||||
@Native public void markSpecial(FunctionValue... funcs) {
|
@Native public void markSpecial(FunctionValue ...funcs) {
|
||||||
for (var func : funcs) {
|
for (var func : funcs) {
|
||||||
func.special = true;
|
func.special = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Native public Environment getEnv(Object func) {
|
@Native public FunctionContext getEnv(Object func) {
|
||||||
if (func instanceof CodeFunction) return ((CodeFunction)func).environment;
|
if (func instanceof CodeFunction) return ((CodeFunction)func).environment;
|
||||||
else return null;
|
else return null;
|
||||||
}
|
}
|
||||||
@Native public Object setEnv(Object func, Environment env) {
|
@Native public Object setEnv(Object func, FunctionContext env) {
|
||||||
if (func instanceof CodeFunction) ((CodeFunction)func).environment = env;
|
if (func instanceof CodeFunction) ((CodeFunction)func).environment = env;
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
@Native public Object apply(CallContext ctx, FunctionValue func, Object thisArg, ArrayValue args) throws InterruptedException {
|
@Native public Object apply(Context ctx, FunctionValue func, Object thisArg, ArrayValue args) throws InterruptedException {
|
||||||
return func.call(ctx, thisArg, args.toArray());
|
return func.call(ctx, thisArg, args.toArray());
|
||||||
}
|
}
|
||||||
@Native public FunctionValue delay(CallContext ctx, double delay, FunctionValue callback) throws InterruptedException {
|
@Native public FunctionValue delay(Context ctx, double delay, FunctionValue callback) throws InterruptedException {
|
||||||
var thread = new Thread((Runnable)() -> {
|
var thread = new Thread((Runnable)() -> {
|
||||||
var ms = (long)delay;
|
var ms = (long)delay;
|
||||||
var ns = (int)((delay - ms) * 10000000);
|
var ns = (int)((delay - ms) * 10000000);
|
||||||
@ -38,7 +38,7 @@ public class Internals {
|
|||||||
}
|
}
|
||||||
catch (InterruptedException e) { return; }
|
catch (InterruptedException e) { return; }
|
||||||
|
|
||||||
ctx.engine.pushMsg(false, ctx.data(), ctx.environment, callback, null);
|
ctx.message.engine.pushMsg(false, ctx.message, callback, null);
|
||||||
});
|
});
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
||||||
@ -47,8 +47,8 @@ public class Internals {
|
|||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@Native public void pushMessage(CallContext ctx, boolean micro, FunctionValue func, Object thisArg, Object[] args) {
|
@Native public void pushMessage(Context ctx, boolean micro, FunctionValue func, Object thisArg, Object[] args) {
|
||||||
ctx.engine.pushMsg(micro, ctx.data(), ctx.environment, func, thisArg, args);
|
ctx.message.engine.pushMsg(micro, ctx.message, func, thisArg, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public int strlen(String str) {
|
@Native public int strlen(String str) {
|
||||||
@ -74,6 +74,13 @@ public class Internals {
|
|||||||
return str.value;
|
return str.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Native public static void log(Context ctx, Object ...args) throws InterruptedException {
|
||||||
|
for (var arg : args) {
|
||||||
|
Values.printValue(ctx, arg);
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
@Native public boolean isArray(Object obj) {
|
@Native public boolean isArray(Object obj) {
|
||||||
return obj instanceof ArrayValue;
|
return obj instanceof ArrayValue;
|
||||||
}
|
}
|
||||||
@ -81,14 +88,14 @@ public class Internals {
|
|||||||
return new GeneratorFunction(obj);
|
return new GeneratorFunction(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public boolean defineField(CallContext ctx, ObjectValue obj, Object key, Object val, boolean writable, boolean enumerable, boolean configurable) {
|
@Native public boolean defineField(Context ctx, ObjectValue obj, Object key, Object val, boolean writable, boolean enumerable, boolean configurable) {
|
||||||
return obj.defineProperty(ctx, key, val, writable, configurable, enumerable);
|
return obj.defineProperty(ctx, key, val, writable, configurable, enumerable);
|
||||||
}
|
}
|
||||||
@Native public boolean defineProp(CallContext ctx, ObjectValue obj, Object key, FunctionValue getter, FunctionValue setter, boolean enumerable, boolean configurable) {
|
@Native public boolean defineProp(Context ctx, ObjectValue obj, Object key, FunctionValue getter, FunctionValue setter, boolean enumerable, boolean configurable) {
|
||||||
return obj.defineProperty(ctx, key, getter, setter, configurable, enumerable);
|
return obj.defineProperty(ctx, key, getter, setter, configurable, enumerable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public ArrayValue keys(CallContext ctx, Object obj, boolean onlyString) throws InterruptedException {
|
@Native public ArrayValue keys(Context ctx, Object obj, boolean onlyString) throws InterruptedException {
|
||||||
var res = new ArrayValue();
|
var res = new ArrayValue();
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
@ -98,7 +105,7 @@ public class Internals {
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@Native public ArrayValue ownPropKeys(CallContext ctx, Object obj, boolean symbols) throws InterruptedException {
|
@Native public ArrayValue ownPropKeys(Context ctx, Object obj, boolean symbols) throws InterruptedException {
|
||||||
var res = new ArrayValue();
|
var res = new ArrayValue();
|
||||||
|
|
||||||
if (Values.isObject(obj)) {
|
if (Values.isObject(obj)) {
|
||||||
@ -110,7 +117,7 @@ public class Internals {
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@Native public ObjectValue ownProp(CallContext ctx, ObjectValue val, Object key) throws InterruptedException {
|
@Native public ObjectValue ownProp(Context ctx, ObjectValue val, Object key) throws InterruptedException {
|
||||||
return val.getMemberDescriptor(ctx, key);
|
return val.getMemberDescriptor(ctx, key);
|
||||||
}
|
}
|
||||||
@Native public void lock(ObjectValue val, String type) {
|
@Native public void lock(ObjectValue val, String type) {
|
||||||
@ -124,7 +131,7 @@ public class Internals {
|
|||||||
return val.extensible();
|
return val.extensible();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native public void sort(CallContext ctx, ArrayValue arr, FunctionValue cmp) {
|
@Native public void sort(Context ctx, ArrayValue arr, FunctionValue cmp) {
|
||||||
arr.sort((a, b) -> {
|
arr.sort((a, b) -> {
|
||||||
try {
|
try {
|
||||||
var res = Values.toNumber(ctx, cmp.call(ctx, null, a, b));
|
var res = Values.toNumber(ctx, cmp.call(ctx, null, a, b));
|
||||||
|
@ -3,7 +3,7 @@ package me.topchetoeu.jscript.polyfills;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
import me.topchetoeu.jscript.engine.values.Values;
|
||||||
@ -30,7 +30,7 @@ public class JSON {
|
|||||||
if (val.isNull()) return Values.NULL;
|
if (val.isNull()) return Values.NULL;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private static JSONElement toJSON(CallContext ctx, Object val, HashSet<Object> prev) throws InterruptedException {
|
private static JSONElement toJSON(Context ctx, Object val, HashSet<Object> prev) throws InterruptedException {
|
||||||
if (val instanceof Boolean) return JSONElement.bool((boolean)val);
|
if (val instanceof Boolean) return JSONElement.bool((boolean)val);
|
||||||
if (val instanceof Number) return JSONElement.number(((Number)val).doubleValue());
|
if (val instanceof Number) return JSONElement.number(((Number)val).doubleValue());
|
||||||
if (val instanceof String) return JSONElement.string((String)val);
|
if (val instanceof String) return JSONElement.string((String)val);
|
||||||
@ -70,7 +70,7 @@ public class JSON {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static Object parse(CallContext ctx, String val) throws InterruptedException {
|
public static Object parse(Context ctx, String val) throws InterruptedException {
|
||||||
try {
|
try {
|
||||||
return toJS(me.topchetoeu.jscript.json.JSON.parse("<value>", val));
|
return toJS(me.topchetoeu.jscript.json.JSON.parse("<value>", val));
|
||||||
}
|
}
|
||||||
@ -79,7 +79,7 @@ public class JSON {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static String stringify(CallContext ctx, Object val) throws InterruptedException {
|
public static String stringify(Context ctx, Object val) throws InterruptedException {
|
||||||
return me.topchetoeu.jscript.json.JSON.stringify(toJSON(ctx, val, new HashSet<>()));
|
return me.topchetoeu.jscript.json.JSON.stringify(toJSON(ctx, val, new HashSet<>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.polyfills;
|
package me.topchetoeu.jscript.polyfills;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.MessageContext;
|
||||||
import me.topchetoeu.jscript.interop.Native;
|
import me.topchetoeu.jscript.interop.Native;
|
||||||
|
|
||||||
public class Math {
|
public class Math {
|
||||||
@ -22,19 +22,19 @@ public class Math {
|
|||||||
public static final double LOG10E = java.lang.Math.log10(java.lang.Math.E);
|
public static final double LOG10E = java.lang.Math.log10(java.lang.Math.E);
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double asin(CallContext ctx, double x) throws InterruptedException {
|
public static double asin(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.asin(x);
|
return java.lang.Math.asin(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double acos(CallContext ctx, double x) throws InterruptedException {
|
public static double acos(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.acos(x);
|
return java.lang.Math.acos(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double atan(CallContext ctx, double x) throws InterruptedException {
|
public static double atan(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.atan(x);
|
return java.lang.Math.atan(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double atan2(CallContext ctx, double y, double x) throws InterruptedException {
|
public static double atan2(MessageContext ctx, double y, double x) throws InterruptedException {
|
||||||
double _y = y;
|
double _y = y;
|
||||||
double _x = x;
|
double _x = x;
|
||||||
if (_x == 0) {
|
if (_x == 0) {
|
||||||
@ -51,59 +51,59 @@ public class Math {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double asinh(CallContext ctx, double x) throws InterruptedException {
|
public static double asinh(MessageContext ctx, double x) throws InterruptedException {
|
||||||
double _x = x;
|
double _x = x;
|
||||||
return java.lang.Math.log(_x + java.lang.Math.sqrt(_x * _x + 1));
|
return java.lang.Math.log(_x + java.lang.Math.sqrt(_x * _x + 1));
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double acosh(CallContext ctx, double x) throws InterruptedException {
|
public static double acosh(MessageContext ctx, double x) throws InterruptedException {
|
||||||
double _x = x;
|
double _x = x;
|
||||||
return java.lang.Math.log(_x + java.lang.Math.sqrt(_x * _x - 1));
|
return java.lang.Math.log(_x + java.lang.Math.sqrt(_x * _x - 1));
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double atanh(CallContext ctx, double x) throws InterruptedException {
|
public static double atanh(MessageContext ctx, double x) throws InterruptedException {
|
||||||
double _x = x;
|
double _x = x;
|
||||||
if (_x <= -1 || _x >= 1) return Double.NaN;
|
if (_x <= -1 || _x >= 1) return Double.NaN;
|
||||||
return .5 * java.lang.Math.log((1 + _x) / (1 - _x));
|
return .5 * java.lang.Math.log((1 + _x) / (1 - _x));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double sin(CallContext ctx, double x) throws InterruptedException {
|
public static double sin(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.sin(x);
|
return java.lang.Math.sin(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double cos(CallContext ctx, double x) throws InterruptedException {
|
public static double cos(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.cos(x);
|
return java.lang.Math.cos(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double tan(CallContext ctx, double x) throws InterruptedException {
|
public static double tan(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.tan(x);
|
return java.lang.Math.tan(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double sinh(CallContext ctx, double x) throws InterruptedException {
|
public static double sinh(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.sinh(x);
|
return java.lang.Math.sinh(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double cosh(CallContext ctx, double x) throws InterruptedException {
|
public static double cosh(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.cosh(x);
|
return java.lang.Math.cosh(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double tanh(CallContext ctx, double x) throws InterruptedException {
|
public static double tanh(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.tanh(x);
|
return java.lang.Math.tanh(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double sqrt(CallContext ctx, double x) throws InterruptedException {
|
public static double sqrt(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.sqrt(x);
|
return java.lang.Math.sqrt(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double cbrt(CallContext ctx, double x) throws InterruptedException {
|
public static double cbrt(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.cbrt(x);
|
return java.lang.Math.cbrt(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double hypot(CallContext ctx, double... vals) throws InterruptedException {
|
public static double hypot(MessageContext ctx, double ...vals) throws InterruptedException {
|
||||||
var res = 0.;
|
var res = 0.;
|
||||||
for (var el : vals) {
|
for (var el : vals) {
|
||||||
var val = el;
|
var val = el;
|
||||||
@ -112,68 +112,68 @@ public class Math {
|
|||||||
return java.lang.Math.sqrt(res);
|
return java.lang.Math.sqrt(res);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static int imul(CallContext ctx, double a, double b) throws InterruptedException {
|
public static int imul(MessageContext ctx, double a, double b) throws InterruptedException {
|
||||||
return (int)a * (int)b;
|
return (int)a * (int)b;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double exp(CallContext ctx, double x) throws InterruptedException {
|
public static double exp(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.exp(x);
|
return java.lang.Math.exp(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double expm1(CallContext ctx, double x) throws InterruptedException {
|
public static double expm1(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.expm1(x);
|
return java.lang.Math.expm1(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double pow(CallContext ctx, double x, double y) throws InterruptedException {
|
public static double pow(MessageContext ctx, double x, double y) throws InterruptedException {
|
||||||
return java.lang.Math.pow(x, y);
|
return java.lang.Math.pow(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double log(CallContext ctx, double x) throws InterruptedException {
|
public static double log(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.log(x);
|
return java.lang.Math.log(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double log10(CallContext ctx, double x) throws InterruptedException {
|
public static double log10(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.log10(x);
|
return java.lang.Math.log10(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double log1p(CallContext ctx, double x) throws InterruptedException {
|
public static double log1p(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.log1p(x);
|
return java.lang.Math.log1p(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double log2(CallContext ctx, double x) throws InterruptedException {
|
public static double log2(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.log(x) / LN2;
|
return java.lang.Math.log(x) / LN2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double ceil(CallContext ctx, double x) throws InterruptedException {
|
public static double ceil(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.ceil(x);
|
return java.lang.Math.ceil(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double floor(CallContext ctx, double x) throws InterruptedException {
|
public static double floor(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.floor(x);
|
return java.lang.Math.floor(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double round(CallContext ctx, double x) throws InterruptedException {
|
public static double round(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.round(x);
|
return java.lang.Math.round(x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static float fround(CallContext ctx, double x) throws InterruptedException {
|
public static float fround(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return (float)x;
|
return (float)x;
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double trunc(CallContext ctx, double x) throws InterruptedException {
|
public static double trunc(MessageContext ctx, double x) throws InterruptedException {
|
||||||
var _x = x;
|
var _x = x;
|
||||||
return java.lang.Math.floor(java.lang.Math.abs(_x)) * java.lang.Math.signum(_x);
|
return java.lang.Math.floor(java.lang.Math.abs(_x)) * java.lang.Math.signum(_x);
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double abs(CallContext ctx, double x) throws InterruptedException {
|
public static double abs(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.abs(x);
|
return java.lang.Math.abs(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double max(CallContext ctx, double... vals) throws InterruptedException {
|
public static double max(MessageContext ctx, double ...vals) throws InterruptedException {
|
||||||
var res = Double.NEGATIVE_INFINITY;
|
var res = Double.NEGATIVE_INFINITY;
|
||||||
|
|
||||||
for (var el : vals) {
|
for (var el : vals) {
|
||||||
@ -184,7 +184,7 @@ public class Math {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static double min(CallContext ctx, double... vals) throws InterruptedException {
|
public static double min(MessageContext ctx, double ...vals) throws InterruptedException {
|
||||||
var res = Double.POSITIVE_INFINITY;
|
var res = Double.POSITIVE_INFINITY;
|
||||||
|
|
||||||
for (var el : vals) {
|
for (var el : vals) {
|
||||||
@ -196,7 +196,7 @@ public class Math {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static double sign(CallContext ctx, double x) throws InterruptedException {
|
public static double sign(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return java.lang.Math.signum(x);
|
return java.lang.Math.signum(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ public class Math {
|
|||||||
return java.lang.Math.random();
|
return java.lang.Math.random();
|
||||||
}
|
}
|
||||||
@Native
|
@Native
|
||||||
public static int clz32(CallContext ctx, double x) throws InterruptedException {
|
public static int clz32(MessageContext ctx, double x) throws InterruptedException {
|
||||||
return Integer.numberOfLeadingZeros((int)x);
|
return Integer.numberOfLeadingZeros((int)x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
package me.topchetoeu.jscript.polyfills;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.Engine;
|
|
||||||
import me.topchetoeu.jscript.engine.modules.ModuleManager;
|
|
||||||
|
|
||||||
public class PolyfillEngine extends Engine {
|
|
||||||
public static String streamToString(InputStream in) {
|
|
||||||
try {
|
|
||||||
StringBuilder out = new StringBuilder();
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(in));
|
|
||||||
|
|
||||||
for(var line = br.readLine(); line != null; line = br.readLine()) {
|
|
||||||
out.append(line).append('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
br.close();
|
|
||||||
return out.toString();
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static String resourceToString(String name) {
|
|
||||||
var str = PolyfillEngine.class.getResourceAsStream("/me/topchetoeu/jscript/" + name);
|
|
||||||
if (str == null) return null;
|
|
||||||
return streamToString(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final ModuleManager modules;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object makeRegex(String pattern, String flags) {
|
|
||||||
return new RegExp(pattern, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ModuleManager modules() {
|
|
||||||
return modules;
|
|
||||||
}
|
|
||||||
public PolyfillEngine(File root) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.modules = new ModuleManager(root);
|
|
||||||
|
|
||||||
// exposeNamespace("Math", Math.class);
|
|
||||||
// exposeNamespace("JSON", JSON.class);
|
|
||||||
// exposeClass("Promise", Promise.class);
|
|
||||||
// exposeClass("RegExp", RegExp.class);
|
|
||||||
// exposeClass("Date", Date.class);
|
|
||||||
// exposeClass("Map", Map.class);
|
|
||||||
// exposeClass("Set", Set.class);
|
|
||||||
|
|
||||||
// global().define("Object", "Function", "String", "Number", "Boolean", "Symbol");
|
|
||||||
// global().define("Array", "require");
|
|
||||||
// global().define("Error", "SyntaxError", "TypeError", "RangeError");
|
|
||||||
// global().define("setTimeout", "setInterval", "clearTimeout", "clearInterval");
|
|
||||||
// global().define("debugger");
|
|
||||||
|
|
||||||
// global().define(true, new NativeFunction("measure", (ctx, thisArg, values) -> {
|
|
||||||
// var start = System.nanoTime();
|
|
||||||
// try {
|
|
||||||
// return Values.call(ctx, values[0], ctx);
|
|
||||||
// }
|
|
||||||
// finally {
|
|
||||||
// System.out.println(String.format("Function took %s ms", (System.nanoTime() - start) / 1000000.));
|
|
||||||
// }
|
|
||||||
// }));
|
|
||||||
// global().define(true, new NativeFunction("isNaN", (ctx, thisArg, args) -> {
|
|
||||||
// if (args.length == 0) return true;
|
|
||||||
// else return Double.isNaN(Values.toNumber(ctx, args[0]));
|
|
||||||
// }));
|
|
||||||
// global().define(true, new NativeFunction("log", (el, t, args) -> {
|
|
||||||
// for (var obj : args) Values.printValue(el, obj);
|
|
||||||
// System.out.println();
|
|
||||||
// return null;
|
|
||||||
// }));
|
|
||||||
|
|
||||||
// var scope = global().globalChild();
|
|
||||||
// scope.define("gt", true, global().obj);
|
|
||||||
// scope.define("lgt", true, scope.obj);
|
|
||||||
// scope.define("setProps", "setConstr");
|
|
||||||
// scope.define("internals", true, new Internals());
|
|
||||||
// scope.define(true, new NativeFunction("run", (ctx, thisArg, args) -> {
|
|
||||||
// var filename = (String)args[0];
|
|
||||||
// boolean pollute = args.length > 1 && args[1].equals(true);
|
|
||||||
// FunctionValue func;
|
|
||||||
// var src = resourceToString("js/" + filename);
|
|
||||||
// if (src == null) throw new RuntimeException("The source '" + filename + "' doesn't exist.");
|
|
||||||
|
|
||||||
// if (pollute) func = Parsing.compile(global(), filename, src);
|
|
||||||
// else func = Parsing.compile(scope.globalChild(), filename, src);
|
|
||||||
|
|
||||||
// func.call(ctx);
|
|
||||||
// return null;
|
|
||||||
// }));
|
|
||||||
|
|
||||||
// pushMsg(false, scope.globalChild(), java.util.Map.of(), "core.js", resourceToString("js/core.js"), null);
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ package me.topchetoeu.jscript.polyfills;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.CallContext;
|
import me.topchetoeu.jscript.engine.Context;
|
||||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
||||||
import me.topchetoeu.jscript.engine.values.NativeWrapper;
|
import me.topchetoeu.jscript.engine.values.NativeWrapper;
|
||||||
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
import me.topchetoeu.jscript.engine.values.ObjectValue;
|
||||||
@ -17,7 +17,7 @@ public class RegExp {
|
|||||||
private static final Pattern NAMED_PATTERN = Pattern.compile("\\(\\?<([^=!].*?)>", Pattern.DOTALL);
|
private static final Pattern NAMED_PATTERN = Pattern.compile("\\(\\?<([^=!].*?)>", Pattern.DOTALL);
|
||||||
private static final Pattern ESCAPE_PATTERN = Pattern.compile("[/\\-\\\\^$*+?.()|\\[\\]{}]");
|
private static final Pattern ESCAPE_PATTERN = Pattern.compile("[/\\-\\\\^$*+?.()|\\[\\]{}]");
|
||||||
|
|
||||||
private static String cleanupPattern(CallContext ctx, Object val) throws InterruptedException {
|
private static String cleanupPattern(Context ctx, Object val) throws InterruptedException {
|
||||||
if (val == null) return "(?:)";
|
if (val == null) return "(?:)";
|
||||||
if (val instanceof RegExp) return ((RegExp)val).source;
|
if (val instanceof RegExp) return ((RegExp)val).source;
|
||||||
if (val instanceof NativeWrapper && ((NativeWrapper)val).wrapped instanceof RegExp) {
|
if (val instanceof NativeWrapper && ((NativeWrapper)val).wrapped instanceof RegExp) {
|
||||||
@ -27,7 +27,7 @@ public class RegExp {
|
|||||||
if (res.equals("")) return "(?:)";
|
if (res.equals("")) return "(?:)";
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
private static String cleanupFlags(CallContext ctx, Object val) throws InterruptedException {
|
private static String cleanupFlags(Context ctx, Object val) throws InterruptedException {
|
||||||
if (val == null) return "";
|
if (val == null) return "";
|
||||||
return Values.toString(ctx, val);
|
return Values.toString(ctx, val);
|
||||||
}
|
}
|
||||||
@ -46,7 +46,7 @@ public class RegExp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public static RegExp escape(CallContext ctx, Object raw, Object flags) throws InterruptedException {
|
public static RegExp escape(Context ctx, Object raw, Object flags) throws InterruptedException {
|
||||||
return escape(Values.toString(ctx, raw), cleanupFlags(ctx, flags));
|
return escape(Values.toString(ctx, raw), cleanupFlags(ctx, flags));
|
||||||
}
|
}
|
||||||
public static RegExp escape(String raw, String flags) {
|
public static RegExp escape(String raw, String flags) {
|
||||||
@ -79,7 +79,7 @@ public class RegExp {
|
|||||||
@NativeGetter("lastIndex")
|
@NativeGetter("lastIndex")
|
||||||
public int lastIndex() { return lastI; }
|
public int lastIndex() { return lastI; }
|
||||||
@NativeSetter("lastIndex")
|
@NativeSetter("lastIndex")
|
||||||
public void setLastIndex(CallContext ctx, Object i) throws InterruptedException {
|
public void setLastIndex(Context ctx, Object i) throws InterruptedException {
|
||||||
lastI = (int)Values.toNumber(ctx, i);
|
lastI = (int)Values.toNumber(ctx, i);
|
||||||
}
|
}
|
||||||
public void setLastIndex(int i) {
|
public void setLastIndex(int i) {
|
||||||
@ -100,7 +100,7 @@ public class RegExp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public Object exec(CallContext ctx, Object str) throws InterruptedException {
|
public Object exec(Context ctx, Object str) throws InterruptedException {
|
||||||
return exec(Values.toString(ctx, str));
|
return exec(Values.toString(ctx, str));
|
||||||
}
|
}
|
||||||
public Object exec(String str) {
|
public Object exec(String str) {
|
||||||
@ -150,7 +150,7 @@ public class RegExp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Native
|
@Native
|
||||||
public RegExp(CallContext ctx, Object pattern, Object flags) throws InterruptedException {
|
public RegExp(Context ctx, Object pattern, Object flags) throws InterruptedException {
|
||||||
this(cleanupPattern(ctx, pattern), cleanupFlags(ctx, flags));
|
this(cleanupPattern(ctx, pattern), cleanupFlags(ctx, flags));
|
||||||
}
|
}
|
||||||
public RegExp(String pattern, String flags) {
|
public RegExp(String pattern, String flags) {
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
package me.topchetoeu.jscript.polyfills;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import me.topchetoeu.jscript.engine.scope.GlobalScope;
|
|
||||||
import me.topchetoeu.jscript.engine.values.ArrayValue;
|
|
||||||
import me.topchetoeu.jscript.engine.values.FunctionValue;
|
|
||||||
import me.topchetoeu.jscript.engine.values.NativeFunction;
|
|
||||||
import me.topchetoeu.jscript.engine.values.Values;
|
|
||||||
|
|
||||||
public class TypescriptEngine extends PolyfillEngine {
|
|
||||||
private FunctionValue ts;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FunctionValue compile(GlobalScope scope, String filename, String raw) throws InterruptedException {
|
|
||||||
if (ts != null) {
|
|
||||||
var res = Values.array(ts.call(context(), null, filename, raw));
|
|
||||||
var src = Values.toString(context(), res.get(0));
|
|
||||||
var func = Values.function(res.get(1));
|
|
||||||
|
|
||||||
var compiled = super.compile(scope, filename, src);
|
|
||||||
|
|
||||||
return new NativeFunction(null, (ctx, thisArg, args) -> {
|
|
||||||
return func.call(context(), null, compiled, thisArg, new ArrayValue(args));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return super.compile(scope, filename, raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypescriptEngine(File root) {
|
|
||||||
super(root);
|
|
||||||
var scope = global().globalChild();
|
|
||||||
|
|
||||||
var decls = new ArrayList<Object>();
|
|
||||||
decls.add(resourceToString("dts/core.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/iterators.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/map.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/promise.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/regex.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/require.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/set.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/values/array.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/values/boolean.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/values/number.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/values/errors.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/values/function.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/values/object.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/values/string.d.ts"));
|
|
||||||
decls.add(resourceToString("dts/values/symbol.d.ts"));
|
|
||||||
|
|
||||||
scope.define("libs", true, ArrayValue.of(decls));
|
|
||||||
scope.define(true, new NativeFunction("init", (el, t, args) -> {
|
|
||||||
ts = Values.function(args[0]);
|
|
||||||
return null;
|
|
||||||
}));
|
|
||||||
|
|
||||||
pushMsg(false, scope, Map.of(), "bootstrap.js", resourceToString("js/bootstrap.js"), null);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user