Debugging support #7

Merged
TopchetoEU merged 7 commits from TopcehtoEU/debugging into master 2023-10-28 14:11:55 +00:00
22 changed files with 226 additions and 211 deletions
Showing only changes of commit 517e3e6657 - Show all commits

View File

@ -7,7 +7,7 @@ import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import me.topchetoeu.jscript.engine.Message;
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Engine;
import me.topchetoeu.jscript.engine.Environment;
import me.topchetoeu.jscript.engine.values.NativeFunction;
@ -65,7 +65,7 @@ public class Main {
env = new Environment(null, null, null);
var exited = new boolean[1];
engine.pushMsg(false, new Message(engine), new NativeFunction((ctx, thisArg, _a) -> {
engine.pushMsg(false, null, new NativeFunction((ctx, thisArg, _a) -> {
new Internals().apply(env);
env.global.define("exit", _ctx -> {
@ -94,7 +94,7 @@ public class Main {
var raw = in.readLine();
if (raw == null) break;
engine.pushMsg(false, env.context(new Message(engine)), "<stdio>", raw, null).toObservable().once(valuePrinter);
engine.pushMsg(false, new Context(engine).pushEnv(env), "<stdio>", raw, null).toObservable().once(valuePrinter);
}
catch (EngineException e) {
try {

View File

@ -1,27 +1,39 @@
package me.topchetoeu.jscript.engine;
import java.util.Stack;
import me.topchetoeu.jscript.engine.values.FunctionValue;
import me.topchetoeu.jscript.engine.values.Values;
import me.topchetoeu.jscript.parsing.Parsing;
public class Context {
public final Environment env;
public final Message message;
private final Stack<Environment> env = new Stack<>();
public final Data data;
public final Engine engine;
public Environment environment() {
return env.empty() ? null : env.peek();
}
public Context pushEnv(Environment env) {
this.env.push(env);
return this;
}
public void popEnv() {
if (!env.empty()) this.env.pop();
}
public FunctionValue compile(String filename, String raw) throws InterruptedException {
var res = Values.toString(this, env.compile.call(this, null, raw, filename));
return Parsing.compile(message.engine.functions, env, filename, res);
var res = Values.toString(this, environment().compile.call(this, null, raw, filename));
return Parsing.compile(engine.functions, environment(), filename, res);
}
public Context setEnv(Environment env) {
return new Context(env, message);
public Context(Engine engine, Data data) {
this.data = new Data(engine.data);
if (data != null) this.data.addAll(data);
this.engine = engine;
}
public Context setMsg(Message msg) {
return new Context(env, msg);
}
public Context(Environment env, Message msg) {
this.env = env;
this.message = msg;
public Context(Engine engine) {
this(engine, null);
}
}

View File

@ -1,43 +1,53 @@
package me.topchetoeu.jscript.engine;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Map;
@SuppressWarnings("unchecked")
public class Data implements Iterable<Entry<DataKey<?>, ?>> {
public class Data {
public final Data parent;
private HashMap<DataKey<Object>, Object> data = new HashMap<>();
public Data copy() {
return new Data().addAll(this);
}
public Data addAll(Iterable<Entry<DataKey<?>, ?>> data) {
for (var el : data) {
add((DataKey<Object>)el.getKey(), (Object)el.getValue());
public Data addAll(Map<DataKey<?>, ?> data) {
for (var el : data.entrySet()) {
get((DataKey<Object>)el.getKey(), (Object)el.getValue());
}
return this;
}
public Data addAll(Data data) {
for (var el : data.data.entrySet()) {
get((DataKey<Object>)el.getKey(), (Object)el.getValue());
}
return this;
}
public <T> T remove(DataKey<T> key) {
return (T)data.remove(key);
}
public <T> Data set(DataKey<T> key, T val) {
if (val == null) data.remove(key);
else data.put((DataKey<Object>)key, (Object)val);
data.put((DataKey<Object>)key, (Object)val);
return this;
}
public <T> T add(DataKey<T> key, T val) {
if (data.containsKey(key)) return (T)data.get(key);
else {
if (val == null) data.remove(key);
else data.put((DataKey<Object>)key, (Object)val);
return val;
public <T> T get(DataKey<T> key, T val) {
for (var it = this; it != null; it = it.parent) {
if (it.data.containsKey(key)) {
this.set(key, val);
return (T)data.get((DataKey<Object>)key);
}
}
set(key, val);
return val;
}
public <T> T get(DataKey<T> key) {
return get(key, null);
}
public <T> T get(DataKey<T> key, T defaultVal) {
if (!has(key)) return defaultVal;
else return (T)data.get(key);
for (var it = this; it != null; it = it.parent) {
if (it.data.containsKey(key)) return (T)data.get((DataKey<Object>)key);
}
return null;
}
public boolean has(DataKey<?> key) { return data.containsKey(key); }
@ -53,8 +63,10 @@ public class Data implements Iterable<Entry<DataKey<?>, ?>> {
return increase(key, 1, 0);
}
@Override
public Iterator<Entry<DataKey<?>, ?>> iterator() {
return (Iterator<Entry<DataKey<?>, ?>>)data.entrySet();
public Data() {
this.parent = null;
}
public Data(Data parent) {
this.parent = parent;
}
}

View File

@ -13,19 +13,18 @@ public class Engine {
private class UncompiledFunction extends FunctionValue {
public final String filename;
public final String raw;
public final Environment env;
private FunctionValue compiled = null;
@Override
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
ctx = ctx.setEnv(env);
return ctx.compile(filename, raw).call(ctx, thisArg, args);
if (compiled == null) compiled = ctx.compile(filename, raw);
return compiled.call(ctx, thisArg, args);
}
public UncompiledFunction(Environment env, String filename, String raw) {
public UncompiledFunction(String filename, String raw) {
super(filename, 0);
this.filename = filename;
this.raw = raw;
this.env = env;
}
}
@ -34,10 +33,10 @@ public class Engine {
public final Object thisArg;
public final Object[] args;
public final DataNotifier<Object> notifier = new DataNotifier<>();
public final Message msg;
public final Context ctx;
public Task(Message ctx, FunctionValue func, Object thisArg, Object[] args) {
this.msg = ctx;
public Task(Context ctx, FunctionValue func, Object thisArg, Object[] args) {
this.ctx = ctx;
this.func = func;
this.thisArg = thisArg;
this.args = args;
@ -52,10 +51,11 @@ public class Engine {
public final int id = ++nextId;
public final HashMap<Long, Instruction[]> functions = new HashMap<>();
public final Data data = new Data().set(StackData.MAX_FRAMES, 10000);
private void runTask(Task task) throws InterruptedException {
try {
task.notifier.next(task.func.call(task.msg.context(null), task.thisArg, task.args));
task.notifier.next(task.func.call(task.ctx, task.thisArg, task.args));
}
catch (InterruptedException e) {
task.notifier.error(new RuntimeException(e));
@ -105,17 +105,13 @@ public class Engine {
return this.thread != null;
}
public Awaitable<Object> pushMsg(boolean micro, Message ctx, FunctionValue func, Object thisArg, Object ...args) {
var msg = new Task(ctx, func, thisArg, args);
public Awaitable<Object> pushMsg(boolean micro, Context ctx, FunctionValue func, Object thisArg, Object ...args) {
var msg = new Task(ctx == null ? new Context(this) : ctx, func, thisArg, args);
if (micro) microTasks.addLast(msg);
else macroTasks.addLast(msg);
return msg.notifier;
}
public Awaitable<Object> pushMsg(boolean micro, Context ctx, String filename, String raw, Object thisArg, Object ...args) {
return pushMsg(micro, ctx.message, new UncompiledFunction(ctx.env, filename, raw), thisArg, args);
return pushMsg(micro, ctx, new UncompiledFunction(filename, raw), thisArg, args);
}
// public Engine() {
// this.typeRegister = new NativeTypeRegister();
// }
}

View File

@ -20,7 +20,7 @@ public class Environment {
public final HashMap<String, Symbol> symbols = new HashMap<>();
public GlobalScope global;
public WrappersProvider wrappersProvider;
public WrappersProvider wrappers;
@Native public FunctionValue compile;
@Native public FunctionValue regexConstructor = new NativeFunction("RegExp", (ctx, thisArg, args) -> {
@ -57,7 +57,7 @@ public class Environment {
}
@Native public Environment fork() {
var res = new Environment(compile, wrappersProvider, global);
var res = new Environment(compile, wrappers, global);
res.regexConstructor = regexConstructor;
res.prototypes = new HashMap<>(prototypes);
return res;
@ -68,8 +68,11 @@ public class Environment {
return res;
}
public Context context(Message msg) {
return new Context(this, msg);
public Context context(Engine engine, Data data) {
return new Context(engine, data).pushEnv(this);
}
public Context context(Engine engine) {
return new Context(engine).pushEnv(this);
}
public Environment(FunctionValue compile, WrappersProvider nativeConverter, GlobalScope global) {
@ -77,7 +80,7 @@ public class Environment {
if (nativeConverter == null) nativeConverter = new NativeWrapperProvider(this);
if (global == null) global = new GlobalScope();
this.wrappersProvider = nativeConverter;
this.wrappers = nativeConverter;
this.compile = compile;
this.global = global;
}

View File

@ -1,63 +0,0 @@
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 Message {
public final Engine engine;
private final ArrayList<CodeFrame> frames = new ArrayList<>();
public int maxStackFrames = 1000;
public final Data data = new Data();
public List<CodeFrame> frames() { return Collections.unmodifiableList(frames); }
public Message addData(Data data) {
this.data.addAll(data);
return this;
}
public Message pushFrame(Context ctx, CodeFrame frame) throws InterruptedException {
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 List<String> stackTrace() {
var res = new ArrayList<String>();
for (var el : frames) {
var name = el.function.name;
var loc = el.function.loc();
var trace = "";
if (loc != null) trace += "at " + loc.toString() + " ";
if (name != null && !name.equals("")) trace += "in " + name + " ";
trace = trace.trim();
if (!res.equals("")) res.add(trace);
}
return res;
}
public Context context(Environment env) {
return new Context(env, this);
}
public Message(Engine engine) {
this.engine = engine;
}
}

View File

@ -0,0 +1,52 @@
package me.topchetoeu.jscript.engine;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.topchetoeu.jscript.engine.debug.DebugServer;
import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.exceptions.EngineException;
public class StackData {
public static final DataKey<ArrayList<CodeFrame>> FRAMES = new DataKey<>();
public static final DataKey<Integer> MAX_FRAMES = new DataKey<>();
public static final DataKey<DebugServer> DEBUGGER = new DataKey<>();
public static void pushFrame(Context ctx, CodeFrame frame) throws InterruptedException {
var frames = ctx.data.get(FRAMES, new ArrayList<>());
frames.add(frame);
if (frames.size() > ctx.data.get(MAX_FRAMES, 10000)) throw EngineException.ofRange("Stack overflow!");
ctx.pushEnv(frame.function.environment);
}
public static boolean popFrame(Context ctx, CodeFrame frame) {
var frames = ctx.data.get(FRAMES, new ArrayList<>());
if (frames.size() == 0) return false;
if (frames.get(frames.size() - 1) != frame) return false;
frames.remove(frames.size() - 1);
ctx.popEnv();
return true;
}
public static List<CodeFrame> frames(Context ctx) {
return Collections.unmodifiableList(ctx.data.get(FRAMES, new ArrayList<>()));
}
public static List<String> stackTrace(Context ctx) {
var res = new ArrayList<String>();
for (var el : frames(ctx)) {
var name = el.function.name;
var loc = el.function.loc();
var trace = "";
if (loc != null) trace += "at " + loc.toString() + " ";
if (name != null && !name.equals("")) trace += "in " + name + " ";
trace = trace.trim();
if (!trace.equals("")) res.add(trace);
}
return res;
}
}

View File

@ -95,7 +95,7 @@ public class CodeFrame {
private void setCause(Context ctx, EngineException err, EngineException cause) throws InterruptedException {
if (err.value instanceof ObjectValue) {
Values.setMember(ctx, err, ctx.env.symbol("Symbol.cause"), cause);
Values.setMember(ctx, err, ctx.environment().symbol("Symbol.cause"), cause);
}
err.cause = cause;
}
@ -227,19 +227,6 @@ public class CodeFrame {
return Runners.NO_RETURN;
}
public Object run(Context ctx) throws InterruptedException {
try {
ctx.message.pushFrame(ctx, this);
while (true) {
var res = next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, null);
if (res != Runners.NO_RETURN) return res;
}
}
finally {
ctx.message.popFrame(this);
}
}
public CodeFrame(Context ctx, Object thisArg, Object[] args, CodeFunction func) {
this.args = args.clone();
this.scope = new LocalScope(func.localsN, func.captures);

View File

@ -63,7 +63,7 @@ public class Runners {
public static Object execMakeVar(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var name = (String)instr.get(0);
ctx.env.global.define(name);
ctx.environment().global.define(name);
frame.codePtr++;
return NO_RETURN;
}
@ -158,7 +158,7 @@ public class Runners {
public static Object execLoadVar(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
var i = instr.get(0);
if (i instanceof String) frame.push(ctx, ctx.env.global.get(ctx, (String)i));
if (i instanceof String) frame.push(ctx, ctx.environment().global.get(ctx, (String)i));
else frame.push(ctx, frame.scope.get((int)i).get(ctx));
frame.codePtr++;
@ -170,7 +170,7 @@ public class Runners {
return NO_RETURN;
}
public static Object execLoadGlob(Context ctx, Instruction instr, CodeFrame frame) {
frame.push(ctx, ctx.env.global.obj);
frame.push(ctx, ctx.environment().global.obj);
frame.codePtr++;
return NO_RETURN;
}
@ -191,8 +191,8 @@ public class Runners {
captures[i - 3] = frame.scope.get(instr.get(i));
}
var body = ctx.message.engine.functions.get(id);
var func = new CodeFunction(ctx.env, "", localsN, len, captures, body);
var body = ctx.engine.functions.get(id);
var func = new CodeFunction(ctx.environment(), "", localsN, len, captures, body);
frame.push(ctx, func);
@ -217,7 +217,7 @@ public class Runners {
return execLoadMember(ctx, instr, frame);
}
public static Object execLoadRegEx(Context ctx, Instruction instr, CodeFrame frame) throws InterruptedException {
frame.push(ctx, ctx.env.regexConstructor.call(ctx, null, instr.get(0), instr.get(1)));
frame.push(ctx, ctx.environment().regexConstructor.call(ctx, null, instr.get(0), instr.get(1)));
frame.codePtr++;
return NO_RETURN;
}
@ -241,7 +241,7 @@ public class Runners {
var val = (boolean)instr.get(1) ? frame.peek() : frame.pop();
var i = instr.get(0);
if (i instanceof String) ctx.env.global.set(ctx, (String)i, val);
if (i instanceof String) ctx.environment().global.set(ctx, (String)i, val);
else frame.scope.get((int)i).set(ctx, val);
frame.codePtr++;
@ -288,8 +288,8 @@ public class Runners {
Object obj;
if (name != null) {
if (ctx.env.global.has(ctx, name)) {
obj = ctx.env.global.get(ctx, name);
if (ctx.environment().global.has(ctx, name)) {
obj = ctx.environment().global.get(ctx, name);
}
else obj = null;
}

View File

@ -4,7 +4,9 @@ import me.topchetoeu.jscript.Location;
import me.topchetoeu.jscript.compilation.Instruction;
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Environment;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.scope.ValueVariable;
public class CodeFunction extends FunctionValue {
@ -29,7 +31,18 @@ public class CodeFunction extends FunctionValue {
@Override
public Object call(Context ctx, Object thisArg, Object ...args) throws InterruptedException {
return new CodeFrame(ctx, thisArg, args, this).run(ctx.setEnv(environment));
var frame = new CodeFrame(ctx, thisArg, args, this);
try {
StackData.pushFrame(ctx, frame);
while (true) {
var res = frame.next(ctx, Runners.NO_RETURN, Runners.NO_RETURN, null);
if (res != Runners.NO_RETURN) return res;
}
}
finally {
StackData.popFrame(ctx, frame);
}
}
public CodeFunction(Environment environment, String name, int localsN, int length, ValueVariable[] captures, Instruction[] body) {

View File

@ -8,8 +8,7 @@ public class NativeWrapper extends ObjectValue {
@Override
public ObjectValue getPrototype(Context ctx) throws InterruptedException {
if (prototype == NATIVE_PROTO)
return ctx.env.wrappersProvider.getProto(wrapped.getClass());
if (prototype == NATIVE_PROTO) return ctx.environment().wrappers.getProto(wrapped.getClass());
else return super.getPrototype(ctx);
}

View File

@ -147,13 +147,13 @@ public class ObjectValue {
public ObjectValue getPrototype(Context ctx) throws InterruptedException {
try {
if (prototype == OBJ_PROTO) return ctx.env.proto("object");
if (prototype == ARR_PROTO) return ctx.env.proto("array");
if (prototype == FUNC_PROTO) return ctx.env.proto("function");
if (prototype == ERR_PROTO) return ctx.env.proto("error");
if (prototype == RANGE_ERR_PROTO) return ctx.env.proto("rangeErr");
if (prototype == SYNTAX_ERR_PROTO) return ctx.env.proto("syntaxErr");
if (prototype == TYPE_ERR_PROTO) return ctx.env.proto("typeErr");
if (prototype == OBJ_PROTO) return ctx.environment().proto("object");
if (prototype == ARR_PROTO) return ctx.environment().proto("array");
if (prototype == FUNC_PROTO) return ctx.environment().proto("function");
if (prototype == ERR_PROTO) return ctx.environment().proto("error");
if (prototype == RANGE_ERR_PROTO) return ctx.environment().proto("rangeErr");
if (prototype == SYNTAX_ERR_PROTO) return ctx.environment().proto("syntaxErr");
if (prototype == TYPE_ERR_PROTO) return ctx.environment().proto("typeErr");
}
catch (NullPointerException e) {
return null;
@ -172,14 +172,14 @@ public class ObjectValue {
else if (Values.isObject(val)) {
var obj = Values.object(val);
if (ctx != null && ctx.env != null) {
if (obj == ctx.env.proto("object")) prototype = OBJ_PROTO;
else if (obj == ctx.env.proto("array")) prototype = ARR_PROTO;
else if (obj == ctx.env.proto("function")) prototype = FUNC_PROTO;
else if (obj == ctx.env.proto("error")) prototype = ERR_PROTO;
else if (obj == ctx.env.proto("syntaxErr")) prototype = SYNTAX_ERR_PROTO;
else if (obj == ctx.env.proto("typeErr")) prototype = TYPE_ERR_PROTO;
else if (obj == ctx.env.proto("rangeErr")) prototype = RANGE_ERR_PROTO;
if (ctx != null && ctx.environment() != null) {
if (obj == ctx.environment().proto("object")) prototype = OBJ_PROTO;
else if (obj == ctx.environment().proto("array")) prototype = ARR_PROTO;
else if (obj == ctx.environment().proto("function")) prototype = FUNC_PROTO;
else if (obj == ctx.environment().proto("error")) prototype = ERR_PROTO;
else if (obj == ctx.environment().proto("syntaxErr")) prototype = SYNTAX_ERR_PROTO;
else if (obj == ctx.environment().proto("typeErr")) prototype = TYPE_ERR_PROTO;
else if (obj == ctx.environment().proto("rangeErr")) prototype = RANGE_ERR_PROTO;
else prototype = obj;
}
else prototype = obj;

View File

@ -321,10 +321,10 @@ public class Values {
if (isObject(obj)) return object(obj).getPrototype(ctx);
if (ctx == null) return null;
if (obj instanceof String) return ctx.env.proto("string");
else if (obj instanceof Number) return ctx.env.proto("number");
else if (obj instanceof Boolean) return ctx.env.proto("bool");
else if (obj instanceof Symbol) return ctx.env.proto("symbol");
if (obj instanceof String) return ctx.environment().proto("string");
else if (obj instanceof Number) return ctx.environment().proto("number");
else if (obj instanceof Boolean) return ctx.environment().proto("bool");
else if (obj instanceof Symbol) return ctx.environment().proto("symbol");
return null;
}
@ -446,7 +446,7 @@ public class Values {
if (val instanceof Class) {
if (ctx == null) return null;
else return ctx.env.wrappersProvider.getConstr((Class<?>)val);
else return ctx.environment().wrappers.getConstr((Class<?>)val);
}
return new NativeWrapper(val);
@ -520,7 +520,7 @@ public class Values {
public static Iterable<Object> toJavaIterable(Context ctx, Object obj) {
return () -> {
try {
var symbol = ctx.env.symbol("Symbol.iterator");
var symbol = ctx.environment().symbol("Symbol.iterator");
var iteratorFunc = getMember(ctx, obj, symbol);
if (!isFunction(iteratorFunc)) return Collections.emptyIterator();
@ -590,7 +590,7 @@ public class Values {
var res = new ObjectValue();
try {
var key = getMember(ctx, getMember(ctx, ctx.env.proto("symbol"), "constructor"), "iterator");
var key = getMember(ctx, getMember(ctx, ctx.environment().proto("symbol"), "constructor"), "iterator");
res.defineProperty(ctx, key, new NativeFunction("", (_ctx, thisArg, args) -> thisArg));
}
catch (IllegalArgumentException | NullPointerException e) { }

View File

@ -1,6 +1,7 @@
package me.topchetoeu.jscript.lib;
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.values.CodeFunction;
@ -19,7 +20,8 @@ public class AsyncFunctionLib extends FunctionValue {
private void next(Context ctx, Object inducedValue, Object inducedError) throws InterruptedException {
Object res = null;
ctx.message.pushFrame(ctx, frame);
StackData.pushFrame(ctx, frame);
ctx.pushEnv(frame.function.environment);
awaiting = false;
while (!awaiting) {
@ -37,7 +39,7 @@ public class AsyncFunctionLib extends FunctionValue {
}
}
ctx.message.popFrame(frame);
StackData.popFrame(ctx, frame);
if (awaiting) {
PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject));

View File

@ -3,6 +3,7 @@ package me.topchetoeu.jscript.lib;
import java.util.Map;
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.values.CodeFunction;
@ -34,7 +35,7 @@ public class AsyncGeneratorLib extends FunctionValue {
}
Object res = null;
ctx.message.pushFrame(ctx, frame);
StackData.pushFrame(ctx, frame);
state = 0;
while (state == 0) {
@ -55,7 +56,7 @@ public class AsyncGeneratorLib extends FunctionValue {
}
}
ctx.message.popFrame(frame);
StackData.popFrame(ctx, frame);
if (state == 1) {
PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject));

View File

@ -2,6 +2,7 @@ package me.topchetoeu.jscript.lib;
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Environment;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.ObjectValue;
import me.topchetoeu.jscript.engine.values.Values;
@ -52,7 +53,7 @@ public class ErrorLib {
var target = new ObjectValue();
if (thisArg instanceof ObjectValue) target = (ObjectValue)thisArg;
target.defineProperty(ctx, "stack", new ArrayValue(ctx, ctx.message.stackTrace().toArray()));
target.defineProperty(ctx, "stack", new ArrayValue(ctx, StackData.stackTrace(ctx)));
target.defineProperty(ctx, "name", "Error");
if (message == null) target.defineProperty(ctx, "message", "");
else target.defineProperty(ctx, "message", Values.toString(ctx, message));

View File

@ -1,6 +1,7 @@
package me.topchetoeu.jscript.lib;
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.frame.Runners;
import me.topchetoeu.jscript.engine.values.CodeFunction;
@ -30,7 +31,7 @@ public class GeneratorLib extends FunctionValue {
}
Object res = null;
ctx.message.pushFrame(ctx, frame);
StackData.pushFrame(ctx, frame);
yielding = false;
while (!yielding) {
@ -48,7 +49,7 @@ public class GeneratorLib extends FunctionValue {
}
}
ctx.message.popFrame(frame);
StackData.popFrame(ctx, frame);
if (done) frame = null;
else res = frame.pop();

View File

@ -31,12 +31,12 @@ public class Internals {
}
catch (InterruptedException e) { return; }
ctx.message.engine.pushMsg(false, ctx.message, func, null, args);
ctx.engine.pushMsg(false, ctx, func, null, args);
});
thread.start();
int i = ctx.env.data.increase(I, 1, 0);
var threads = ctx.env.data.add(THREADS, new HashMap<>());
int i = ctx.environment().data.increase(I, 1, 0);
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
threads.put(++i, thread);
return i;
}
@ -51,19 +51,19 @@ public class Internals {
}
catch (InterruptedException e) { return; }
ctx.message.engine.pushMsg(false, ctx.message, func, null, args);
ctx.engine.pushMsg(false, ctx, func, null, args);
}
});
thread.start();
int i = ctx.env.data.increase(I, 1, 0);
var threads = ctx.env.data.add(THREADS, new HashMap<>());
int i = ctx.environment().data.increase(I, 1, 0);
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
threads.put(++i, thread);
return i;
}
@Native public static void clearTimeout(Context ctx, int i) {
var threads = ctx.env.data.add(THREADS, new HashMap<>());
var threads = ctx.environment().data.get(THREADS, new HashMap<>());
var thread = threads.remove(i);
if (thread != null) thread.interrupt();
@ -80,7 +80,7 @@ public class Internals {
}
public void apply(Environment env) {
var wp = env.wrappersProvider;
var wp = env.wrappers;
var glob = env.global = new GlobalScope(wp.getNamespace(Internals.class));
glob.define(null, "Math", false, wp.getNamespace(MathLib.class));

View File

@ -194,7 +194,7 @@ public class ObjectLib {
return thisArg;
}
@Native(thisArg = true) public static String toString(Context ctx, Object thisArg) throws InterruptedException {
var name = Values.getMember(ctx, thisArg, ctx.env.symbol("Symbol.typeName"));
var name = Values.getMember(ctx, thisArg, ctx.environment().symbol("Symbol.typeName"));
if (name == null) name = "Unknown";
else name = Values.toString(ctx, name);

View File

@ -6,7 +6,6 @@ import java.util.Map;
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Environment;
import me.topchetoeu.jscript.engine.Message;
import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.FunctionValue;
import me.topchetoeu.jscript.engine.values.NativeFunction;
@ -263,7 +262,7 @@ public class PromiseLib {
else if (state == STATE_REJECTED) {
for (var handle : handles) handle.rejected.call(handle.ctx, null, val);
if (handles.size() == 0) {
ctx.message.engine.pushMsg(true, ctx.message, new NativeFunction((_ctx, _thisArg, _args) -> {
ctx.engine.pushMsg(true, ctx, new NativeFunction((_ctx, _thisArg, _args) -> {
if (!handled) {
try { Values.printError(new EngineException(val).setContext(ctx), "(in promise)"); }
catch (InterruptedException ex) { }
@ -297,9 +296,9 @@ public class PromiseLib {
}
private void handle(Context ctx, FunctionValue fulfill, FunctionValue reject) {
if (state == STATE_FULFILLED) ctx.message.engine.pushMsg(true, new Message(ctx.message.engine), fulfill, null, val);
if (state == STATE_FULFILLED) ctx.engine.pushMsg(true, ctx, fulfill, null, val);
else if (state == STATE_REJECTED) {
ctx.message.engine.pushMsg(true, new Message(ctx.message.engine), reject, null, val);
ctx.engine.pushMsg(true, ctx, reject, null, val);
handled = true;
}
else handles.add(new Handle(ctx, fulfill, reject));

View File

@ -76,7 +76,7 @@ public class StringLib {
var val = passThis(ctx, "indexOf", thisArg);
if (term != null && term != Values.NULL && !(term instanceof String)) {
var search = Values.getMember(ctx, term, ctx.env.symbol("Symbol.search"));
var search = Values.getMember(ctx, term, ctx.environment().symbol("Symbol.search"));
if (search instanceof FunctionValue) {
return (int)Values.toNumber(ctx, ((FunctionValue)search).call(ctx, term, val, false, start));
}
@ -88,7 +88,7 @@ public class StringLib {
var val = passThis(ctx, "lastIndexOf", thisArg);
if (term != null && term != Values.NULL && !(term instanceof String)) {
var search = Values.getMember(ctx, term, ctx.env.symbol("Symbol.search"));
var search = Values.getMember(ctx, term, ctx.environment().symbol("Symbol.search"));
if (search instanceof FunctionValue) {
return (int)Values.toNumber(ctx, ((FunctionValue)search).call(ctx, term, val, true, pos));
}
@ -105,7 +105,7 @@ public class StringLib {
var val = passThis(ctx, "replace", thisArg);
if (term != null && term != Values.NULL && !(term instanceof String)) {
var replace = Values.getMember(ctx, term, ctx.env.symbol("Symbol.replace"));
var replace = Values.getMember(ctx, term, ctx.environment().symbol("Symbol.replace"));
if (replace instanceof FunctionValue) {
return Values.toString(ctx, ((FunctionValue)replace).call(ctx, term, val, replacement));
}
@ -117,7 +117,7 @@ public class StringLib {
var val = passThis(ctx, "replaceAll", thisArg);
if (term != null && term != Values.NULL && !(term instanceof String)) {
var replace = Values.getMember(ctx, term, ctx.env.symbol("Symbol.replace"));
var replace = Values.getMember(ctx, term, ctx.environment().symbol("Symbol.replace"));
if (replace instanceof FunctionValue) {
return Values.toString(ctx, ((FunctionValue)replace).call(ctx, term, val, replacement));
}
@ -132,11 +132,11 @@ public class StringLib {
FunctionValue match;
try {
var _match = Values.getMember(ctx, term, ctx.env.symbol("Symbol.match"));
var _match = Values.getMember(ctx, term, ctx.environment().symbol("Symbol.match"));
if (_match instanceof FunctionValue) match = (FunctionValue)_match;
else if (ctx.env.regexConstructor != null) {
var regex = Values.callNew(ctx, ctx.env.regexConstructor, Values.toString(ctx, term), "");
_match = Values.getMember(ctx, regex, ctx.env.symbol("Symbol.match"));
else if (ctx.environment().regexConstructor != null) {
var regex = Values.callNew(ctx, ctx.environment().regexConstructor, Values.toString(ctx, term), "");
_match = Values.getMember(ctx, regex, ctx.environment().symbol("Symbol.match"));
if (_match instanceof FunctionValue) match = (FunctionValue)_match;
else throw EngineException.ofError("Regular expressions don't support matching.");
}
@ -154,14 +154,14 @@ public class StringLib {
FunctionValue match = null;
try {
var _match = Values.getMember(ctx, term, ctx.env.symbol("Symbol.matchAll"));
var _match = Values.getMember(ctx, term, ctx.environment().symbol("Symbol.matchAll"));
if (_match instanceof FunctionValue) match = (FunctionValue)_match;
}
catch (IllegalArgumentException e) { }
if (match == null && ctx.env.regexConstructor != null) {
var regex = Values.callNew(ctx, ctx.env.regexConstructor, Values.toString(ctx, term), "g");
var _match = Values.getMember(ctx, regex, ctx.env.symbol("Symbol.matchAll"));
if (match == null && ctx.environment().regexConstructor != null) {
var regex = Values.callNew(ctx, ctx.environment().regexConstructor, Values.toString(ctx, term), "g");
var _match = Values.getMember(ctx, regex, ctx.environment().symbol("Symbol.matchAll"));
if (_match instanceof FunctionValue) match = (FunctionValue)_match;
else throw EngineException.ofError("Regular expressions don't support matching.");
}
@ -176,7 +176,7 @@ public class StringLib {
if (lim != null) lim = Values.toNumber(ctx, lim);
if (term != null && term != Values.NULL && !(term instanceof String)) {
var replace = Values.getMember(ctx, term, ctx.env.symbol("Symbol.replace"));
var replace = Values.getMember(ctx, term, ctx.environment().symbol("Symbol.replace"));
if (replace instanceof FunctionValue) {
var tmp = ((FunctionValue)replace).call(ctx, term, val, lim, sensible);

View File

@ -18,14 +18,14 @@ import me.topchetoeu.jscript.interop.NativeInit;
public class SymbolLib {
private static final Map<String, Symbol> symbols = new HashMap<>();
@NativeGetter public static Symbol typeName(Context ctx) { return ctx.env.symbol("Symbol.typeName"); }
@NativeGetter public static Symbol replace(Context ctx) { return ctx.env.symbol("Symbol.replace"); }
@NativeGetter public static Symbol match(Context ctx) { return ctx.env.symbol("Symbol.match"); }
@NativeGetter public static Symbol matchAll(Context ctx) { return ctx.env.symbol("Symbol.matchAll"); }
@NativeGetter public static Symbol split(Context ctx) { return ctx.env.symbol("Symbol.split"); }
@NativeGetter public static Symbol search(Context ctx) { return ctx.env.symbol("Symbol.search"); }
@NativeGetter public static Symbol iterator(Context ctx) { return ctx.env.symbol("Symbol.iterator"); }
@NativeGetter public static Symbol asyncIterator(Context ctx) { return ctx.env.symbol("Symbol.asyncIterator"); }
@NativeGetter public static Symbol typeName(Context ctx) { return ctx.environment().symbol("Symbol.typeName"); }
@NativeGetter public static Symbol replace(Context ctx) { return ctx.environment().symbol("Symbol.replace"); }
@NativeGetter public static Symbol match(Context ctx) { return ctx.environment().symbol("Symbol.match"); }
@NativeGetter public static Symbol matchAll(Context ctx) { return ctx.environment().symbol("Symbol.matchAll"); }
@NativeGetter public static Symbol split(Context ctx) { return ctx.environment().symbol("Symbol.split"); }
@NativeGetter public static Symbol search(Context ctx) { return ctx.environment().symbol("Symbol.search"); }
@NativeGetter public static Symbol iterator(Context ctx) { return ctx.environment().symbol("Symbol.iterator"); }
@NativeGetter public static Symbol asyncIterator(Context ctx) { return ctx.environment().symbol("Symbol.asyncIterator"); }
public final Symbol value;