Integrate typescript #8

Merged
TopchetoEU merged 16 commits from TopchetoEU/tests into master 2023-11-05 18:32:42 +00:00
8 changed files with 278 additions and 242 deletions
Showing only changes of commit ed1009ab69 - Show all commits

View File

@ -1,131 +1,150 @@
package me.topchetoeu.jscript; package me.topchetoeu.jscript;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import me.topchetoeu.jscript.engine.Context; 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.Environment;
import me.topchetoeu.jscript.engine.debug.DebugServer; import me.topchetoeu.jscript.engine.StackData;
import me.topchetoeu.jscript.engine.debug.SimpleDebugger; import me.topchetoeu.jscript.engine.debug.DebugServer;
import me.topchetoeu.jscript.engine.values.ArrayValue; import me.topchetoeu.jscript.engine.debug.SimpleDebugger;
import me.topchetoeu.jscript.engine.values.NativeFunction; import me.topchetoeu.jscript.engine.values.ArrayValue;
import me.topchetoeu.jscript.engine.values.Values; import me.topchetoeu.jscript.engine.values.NativeFunction;
import me.topchetoeu.jscript.events.Observer; import me.topchetoeu.jscript.engine.values.ObjectValue;
import me.topchetoeu.jscript.exceptions.EngineException; import me.topchetoeu.jscript.engine.values.Values;
import me.topchetoeu.jscript.exceptions.InterruptException; import me.topchetoeu.jscript.events.Observer;
import me.topchetoeu.jscript.exceptions.SyntaxException; import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.exceptions.UncheckedException; import me.topchetoeu.jscript.exceptions.InterruptException;
import me.topchetoeu.jscript.lib.Internals; import me.topchetoeu.jscript.exceptions.SyntaxException;
import me.topchetoeu.jscript.lib.Internals;
public class Main {
static Thread engineTask, debugTask; public class Main {
static Engine engine; static Thread engineTask, debugTask;
static Environment env; static Engine engine;
static int j = 0; static Environment env;
static int j = 0;
private static Observer<Object> valuePrinter = new Observer<Object>() {
public void next(Object data) { private static Observer<Object> valuePrinter = new Observer<Object>() {
Values.printValue(null, data); public void next(Object data) {
System.out.println(); Values.printValue(null, data);
} System.out.println();
}
public void error(RuntimeException err) {
Values.printError(err, null); public void error(RuntimeException err) {
} Values.printError(err, null);
}
@Override
public void finish() { @Override
engineTask.interrupt(); public void finish() {
} engineTask.interrupt();
}; }
};
public static void main(String args[]) {
System.out.println(String.format("Running %s v%s by %s", Metadata.NAME, Metadata.VERSION, Metadata.AUTHOR)); public static void main(String args[]) {
engine = new Engine(); System.out.println(String.format("Running %s v%s by %s", Metadata.NAME, Metadata.VERSION, Metadata.AUTHOR));
engine = new Engine(true);
env = new Environment(null, null, null);
var exited = new boolean[1]; env = new Environment(null, null, null);
var server = new DebugServer(); var exited = new boolean[1];
server.targets.put("target", (ws, req) -> SimpleDebugger.get(ws, engine)); var server = new DebugServer();
server.targets.put("target", (ws, req) -> new SimpleDebugger(ws, engine));
engineTask = engine.start();
debugTask = server.start(new InetSocketAddress("127.0.0.1", 9229), true); engineTask = engine.start();
// server.awaitConnection(); debugTask = server.start(new InetSocketAddress("127.0.0.1", 9229), true);
engine.pushMsg(false, null, new NativeFunction((ctx, thisArg, _a) -> { engine.pushMsg(false, null, new NativeFunction((ctx, thisArg, _a) -> {
new Internals().apply(env); new Internals().apply(env);
env.global.define("exit", _ctx -> { env.global.define("exit", _ctx -> {
exited[0] = true; exited[0] = true;
throw new InterruptException(); throw new InterruptException();
}); });
env.global.define("go", _ctx -> { env.global.define("go", _ctx -> {
try { try {
var f = Path.of("do.js"); var f = Path.of("do.js");
var func = _ctx.compile(new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f))); var func = _ctx.compile(new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f)));
return func.call(_ctx); return func.call(_ctx);
} }
catch (IOException e) { catch (IOException e) {
throw new EngineException("Couldn't open do.js"); throw new EngineException("Couldn't open do.js");
} }
}); });
// TODO: make better API
return null; env.global.define(true, new NativeFunction("include", (_ctx, th, __args) -> {
}), null).await(); try {
var currFilename = StackData.peekFrame(_ctx).function.loc().filename();
try { var loc = Path.of("").toAbsolutePath();
var ts = engine.pushMsg( if (currFilename.protocol.equals("file")) loc = Path.of(currFilename.path).getParent();
false, new Context(engine).pushEnv(env), var path = loc.resolve(Path.of(__args.length >= 1 ? Values.toString(_ctx, __args[0]) : ""));
new Filename("file", "/mnt/data/repos/java-jscript/src/me/topchetoeu/jscript/js/ts.js"), var src = Files.readString(path);
Reading.resourceToString("js/ts.js"), null var func = _ctx.compile(Filename.fromFile(path.toFile()), src);
).await(); var callArgs = new ArrayValue();
System.out.println("Loaded typescript!"); if (__args.length >= 2 && __args[1] instanceof ArrayValue) callArgs = (ArrayValue)__args[1];
engine.pushMsg( return func.call(_ctx, null, callArgs);
false, new Context(engine).pushEnv(env.child()), }
new Filename("jscript", "internals/bootstrap.js"), Reading.resourceToString("js/bootstrap.js"), null, catch (IOException e) { throw EngineException.ofError("IOError", "Couldn't open file."); }
ts, env, new ArrayValue(null, Reading.resourceToString("js/lib.d.ts")) }));
).await();
} return null;
catch (EngineException e) { }), null).await();
Values.printError(e, "(while initializing TS)");
System.out.println("engine reported stack trace:"); try {
for (var el : e.stackTrace) { var tsEnv = env.child();
System.out.println(el); tsEnv.global.define(null, "module", false, new ObjectValue());
} engine.pushMsg(
} false, new Context(engine).pushEnv(tsEnv),
new Filename("jscript", "ts.js"),
Reading.resourceToString("js/ts.js"), null
var reader = new Thread(() -> { ).await();
try { System.out.println("Loaded typescript!");
for (var i = 0; ; i++) { engine.pushMsg(
try { false, new Context(engine).pushEnv(env.child()),
var raw = Reading.read(); new Filename("jscript", "internals/bootstrap.js"), Reading.resourceToString("js/bootstrap.js"), null,
tsEnv.global.obj, env, new ArrayValue(null, Reading.resourceToString("js/lib.d.ts"))
if (raw == null) break; ).await();
valuePrinter.next(engine.pushMsg(false, new Context(engine).pushEnv(env), new Filename("jscript", "repl/" + i + ".js"), raw, null).await()); }
} catch (EngineException e) {
catch (EngineException e) { Values.printError(e, ""); } Values.printError(e, "(while initializing TS)");
} }
}
catch (IOException e) { return; } var reader = new Thread(() -> {
catch (SyntaxException ex) { try {
if (exited[0]) return; for (var arg : args) {
System.out.println("Syntax error:" + ex.msg); try {
} var file = Path.of(arg);
catch (RuntimeException ex) { var raw = Files.readString(file);
if (!exited[0]) { valuePrinter.next(engine.pushMsg(false, new Context(engine).pushEnv(env), Filename.fromFile(file.toFile()), raw, null).await());
System.out.println("Internal error ocurred:"); }
ex.printStackTrace(); catch (EngineException e) { Values.printError(e, ""); }
} }
} for (var i = 0; ; i++) {
catch (Throwable e) { throw new UncheckedException(e); } try {
if (exited[0]) debugTask.interrupt(); var raw = Reading.read();
});
reader.setDaemon(true); if (raw == null) break;
reader.setName("STD Reader"); valuePrinter.next(engine.pushMsg(false, new Context(engine).pushEnv(env), new Filename("jscript", "repl/" + i + ".js"), raw, null).await());
reader.start(); }
} catch (EngineException e) { Values.printError(e, ""); }
} }
}
catch (IOException e) { exited[0] = true; }
catch (SyntaxException ex) {
if (exited[0]) return;
System.out.println("Syntax error:" + ex.msg);
}
catch (RuntimeException ex) {
if (!exited[0]) {
System.out.println("Internal error ocurred:");
ex.printStackTrace();
}
}
if (exited[0]) debugTask.interrupt();
});
reader.setDaemon(true);
reader.setName("STD Reader");
reader.start();
}
}

View File

@ -6,7 +6,6 @@ import java.util.TreeSet;
import me.topchetoeu.jscript.Filename; import me.topchetoeu.jscript.Filename;
import me.topchetoeu.jscript.Location; import me.topchetoeu.jscript.Location;
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.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.parsing.Parsing; import me.topchetoeu.jscript.parsing.Parsing;
@ -40,10 +39,9 @@ public class Context {
} }
else source = Values.toString(this, transpiled); else source = Values.toString(this, transpiled);
var debugger = StackData.getDebugger(this);
var breakpoints = new TreeSet<Location>(); var breakpoints = new TreeSet<Location>();
FunctionValue res = Parsing.compile(engine.functions, breakpoints, environment(), filename, source); FunctionValue res = Parsing.compile(engine.functions, breakpoints, environment(), filename, source);
if (debugger != null) debugger.onSource(filename, source, breakpoints); engine.onSource(filename, source, breakpoints);
if (runner != null) res = (FunctionValue)runner.call(this, null, res); if (runner != null) res = (FunctionValue)runner.call(this, null, res);

View File

@ -1,16 +1,22 @@
package me.topchetoeu.jscript.engine; package me.topchetoeu.jscript.engine;
import java.util.HashMap; import java.util.HashMap;
import java.util.TreeSet;
import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingDeque;
import me.topchetoeu.jscript.Filename; import me.topchetoeu.jscript.Filename;
import me.topchetoeu.jscript.Location;
import me.topchetoeu.jscript.compilation.FunctionBody; import me.topchetoeu.jscript.compilation.FunctionBody;
import me.topchetoeu.jscript.compilation.Instruction;
import me.topchetoeu.jscript.engine.debug.DebugController;
import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.engine.values.FunctionValue; import me.topchetoeu.jscript.engine.values.FunctionValue;
import me.topchetoeu.jscript.events.Awaitable; import me.topchetoeu.jscript.events.Awaitable;
import me.topchetoeu.jscript.events.DataNotifier; import me.topchetoeu.jscript.events.DataNotifier;
import me.topchetoeu.jscript.exceptions.EngineException;
import me.topchetoeu.jscript.exceptions.InterruptException; import me.topchetoeu.jscript.exceptions.InterruptException;
public class Engine { public class Engine implements DebugController {
private class UncompiledFunction extends FunctionValue { private class UncompiledFunction extends FunctionValue {
public final Filename filename; public final Filename filename;
public final String raw; public final String raw;
@ -51,8 +57,42 @@ public class Engine {
private LinkedBlockingDeque<Task> microTasks = new LinkedBlockingDeque<>(); private LinkedBlockingDeque<Task> microTasks = new LinkedBlockingDeque<>();
public final int id = ++nextId; public final int id = ++nextId;
public final Data data = new Data().set(StackData.MAX_FRAMES, 200);
public final HashMap<Long, FunctionBody> functions = new HashMap<>(); public final HashMap<Long, FunctionBody> functions = new HashMap<>();
public final Data data = new Data().set(StackData.MAX_FRAMES, 10000); public final boolean debugging;
private final HashMap<Filename, String> sources = new HashMap<>();
private final HashMap<Filename, TreeSet<Location>> bpts = new HashMap<>();
private DebugController debugger;
public boolean attachDebugger(DebugController debugger) {
if (!debugging || this.debugger != null) return false;
for (var source : sources.entrySet()) {
debugger.onSource(source.getKey(), source.getValue(), bpts.get(source.getKey()));
}
this.debugger = debugger;
return true;
}
public boolean detachDebugger() {
if (!debugging || this.debugger == null) return false;
this.debugger = null;
return true;
}
@Override public void onFramePop(Context ctx, CodeFrame frame) {
if (debugging && debugger != null) debugger.onFramePop(ctx, frame);
}
@Override public boolean onInstruction(Context ctx, CodeFrame frame, Instruction instruction, Object returnVal, EngineException error, boolean caught) {
if (debugging && debugger != null) return debugger.onInstruction(ctx, frame, instruction, returnVal, error, caught);
else return false;
}
@Override public void onSource(Filename filename, String source, TreeSet<Location> breakpoints) {
if (!debugging) return;
if (debugger != null) debugger.onSource(filename, source, breakpoints);
sources.put(filename, source);
bpts.put(filename, breakpoints);
}
private void runTask(Task task) { private void runTask(Task task) {
try { try {
@ -108,4 +148,8 @@ public class Engine {
public Awaitable<Object> pushMsg(boolean micro, Context ctx, Filename filename, String raw, Object thisArg, Object ...args) { public Awaitable<Object> pushMsg(boolean micro, Context ctx, Filename filename, String raw, Object thisArg, Object ...args) {
return pushMsg(micro, ctx, new UncompiledFunction(filename, raw), thisArg, args); return pushMsg(micro, ctx, new UncompiledFunction(filename, raw), thisArg, args);
} }
public Engine(boolean debugging) {
this.debugging = debugging;
}
} }

View File

@ -40,8 +40,7 @@ public class Environment {
} }
@Native public Symbol symbol(String name) { @Native public Symbol symbol(String name) {
if (symbols.containsKey(name)) if (symbols.containsKey(name)) return symbols.get(name);
return symbols.get(name);
else { else {
var res = new Symbol(name); var res = new Symbol(name);
symbols.put(name, res); symbols.put(name, res);

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import me.topchetoeu.jscript.Location;
import me.topchetoeu.jscript.engine.debug.Debugger; import me.topchetoeu.jscript.engine.debug.Debugger;
import me.topchetoeu.jscript.engine.frame.CodeFrame; import me.topchetoeu.jscript.engine.frame.CodeFrame;
import me.topchetoeu.jscript.exceptions.EngineException; import me.topchetoeu.jscript.exceptions.EngineException;
@ -25,8 +26,7 @@ public class StackData {
if (frames.get(frames.size() - 1) != frame) return false; if (frames.get(frames.size() - 1) != frame) return false;
frames.remove(frames.size() - 1); frames.remove(frames.size() - 1);
ctx.popEnv(); ctx.popEnv();
var dbg = getDebugger(ctx); ctx.engine.onFramePop(ctx, frame);
if (dbg != null) dbg.onFramePop(ctx, frame);
return true; return true;
} }
public static CodeFrame peekFrame(Context ctx) { public static CodeFrame peekFrame(Context ctx) {
@ -45,7 +45,11 @@ public class StackData {
for (var i = frames.size() - 1; i >= 0; i--) { for (var i = frames.size() - 1; i >= 0; i--) {
var el = frames.get(i); var el = frames.get(i);
var name = el.function.name; var name = el.function.name;
var loc = el.function.loc(); Location loc = null;
for (var j = el.codePtr; j >= 0 && loc == null; j--) loc = el.function.body[j].location;
if (loc == null) loc = el.function.loc();
var trace = ""; var trace = "";
if (loc != null) trace += "at " + loc.toString() + " "; if (loc != null) trace += "at " + loc.toString() + " ";
@ -58,8 +62,4 @@ public class StackData {
return res; return res;
} }
public static Debugger getDebugger(Context ctx) {
return ctx.data.get(DEBUGGER);
}
} }

View File

@ -37,7 +37,4 @@ public interface DebugController {
* @param frame The code frame which was popped out * @param frame The code frame which was popped out
*/ */
void onFramePop(Context ctx, CodeFrame frame); void onFramePop(Context ctx, CodeFrame frame);
void connect();
void disconnect();
} }

View File

@ -1,5 +1,6 @@
package me.topchetoeu.jscript.engine.debug; package me.topchetoeu.jscript.engine.debug;
public interface Debugger extends DebugHandler, DebugController { public interface Debugger extends DebugHandler, DebugController {
void connect();
void disconnect();
} }

View File

@ -31,12 +31,6 @@ import me.topchetoeu.jscript.json.JSON;
import me.topchetoeu.jscript.json.JSONElement; import me.topchetoeu.jscript.json.JSONElement;
import me.topchetoeu.jscript.json.JSONList; import me.topchetoeu.jscript.json.JSONList;
import me.topchetoeu.jscript.json.JSONMap; import me.topchetoeu.jscript.json.JSONMap;
import me.topchetoeu.jscript.lib.DateLib;
import me.topchetoeu.jscript.lib.MapLib;
import me.topchetoeu.jscript.lib.PromiseLib;
import me.topchetoeu.jscript.lib.RegExpLib;
import me.topchetoeu.jscript.lib.SetLib;
import me.topchetoeu.jscript.lib.GeneratorLib.Generator;
public class SimpleDebugger implements Debugger { public class SimpleDebugger implements Debugger {
public static final String CHROME_GET_PROP_FUNC = "function s(e){let t=this;const n=JSON.parse(e);for(let e=0,i=n.length;e<i;++e)t=t[n[e]];return t}"; public static final String CHROME_GET_PROP_FUNC = "function s(e){let t=this;const n=JSON.parse(e);for(let e=0,i=n.length;e<i;++e)t=t[n[e]];return t}";
@ -403,7 +397,7 @@ public class SimpleDebugger implements Debugger {
} }
private RunResult run(Frame codeFrame, String code) { private RunResult run(Frame codeFrame, String code) {
var engine = new Engine(); var engine = new Engine(false);
var env = codeFrame.func.environment.fork(); var env = codeFrame.func.environment.fork();
ObjectValue global = env.global.obj, ObjectValue global = env.global.obj,
@ -415,7 +409,7 @@ public class SimpleDebugger implements Debugger {
env.global = new GlobalScope(local); env.global = new GlobalScope(local);
var ctx = new Context(engine).pushEnv(env); var ctx = new Context(engine).pushEnv(env);
var awaiter = engine.pushMsg(false, ctx, new Filename("temp", "exec"), "(" + code + ")", codeFrame.frame.thisArg, codeFrame.frame.args); var awaiter = engine.pushMsg(false, ctx, new Filename("jscript", "eval"), code, codeFrame.frame.thisArg, codeFrame.frame.args);
engine.run(true); engine.run(true);
@ -594,57 +588,46 @@ public class SimpleDebugger implements Debugger {
} }
@Override public void getProperties(V8Message msg) { @Override public void getProperties(V8Message msg) {
var obj = idToObject.get(Integer.parseInt(msg.params.string("objectId"))); var obj = idToObject.get(Integer.parseInt(msg.params.string("objectId")));
var own = msg.params.bool("ownProperties");
var accessorPropertiesOnly = msg.params.bool("accessorPropertiesOnly", false);
var currOwn = true;
var res = new JSONList(); var res = new JSONList();
var ctx = objectToCtx.get(obj);
while (obj != emptyObject && obj != null) { for (var key : obj.keys(true)) {
var ctx = objectToCtx.get(obj); var propDesc = new JSONMap();
for (var key : obj.keys(true)) { if (obj.properties.containsKey(key)) {
var propDesc = new JSONMap(); var prop = obj.properties.get(key);
if (obj.properties.containsKey(key)) { propDesc.set("name", Values.toString(ctx, key));
var prop = obj.properties.get(key); if (prop.getter != null) propDesc.set("get", serializeObj(ctx, prop.getter));
if (prop.setter != null) propDesc.set("set", serializeObj(ctx, prop.setter));
propDesc.set("name", Values.toString(ctx, key)); propDesc.set("enumerable", obj.memberEnumerable(key));
if (prop.getter != null) propDesc.set("get", serializeObj(ctx, prop.getter)); propDesc.set("configurable", obj.memberConfigurable(key));
if (prop.setter != null) propDesc.set("set", serializeObj(ctx, prop.setter)); propDesc.set("isOwn", true);
propDesc.set("enumerable", obj.memberEnumerable(key)); res.add(propDesc);
propDesc.set("configurable", obj.memberConfigurable(key));
propDesc.set("isOwn", currOwn);
res.add(propDesc);
}
else {
propDesc.set("name", Values.toString(ctx, key));
propDesc.set("value", serializeObj(ctx, obj.getMember(ctx, key)));
propDesc.set("writable", obj.memberWritable(key));
propDesc.set("enumerable", obj.memberEnumerable(key));
propDesc.set("configurable", obj.memberConfigurable(key));
propDesc.set("isOwn", currOwn);
res.add(propDesc);
}
} }
else {
obj = obj.getPrototype(ctx); propDesc.set("name", Values.toString(ctx, key));
propDesc.set("value", serializeObj(ctx, obj.getMember(ctx, key)));
if (currOwn) { propDesc.set("writable", obj.memberWritable(key));
var protoDesc = new JSONMap(); propDesc.set("enumerable", obj.memberEnumerable(key));
protoDesc.set("name", "__proto__"); propDesc.set("configurable", obj.memberConfigurable(key));
protoDesc.set("value", serializeObj(ctx, obj == null ? Values.NULL : obj)); propDesc.set("isOwn", true);
protoDesc.set("writable", true); res.add(propDesc);
protoDesc.set("enumerable", false);
protoDesc.set("configurable", false);
protoDesc.set("isOwn", currOwn);
res.add(protoDesc);
} }
currOwn = false;
if (true) break;
} }
var proto = obj.getPrototype(ctx);
var protoDesc = new JSONMap();
protoDesc.set("name", "__proto__");
protoDesc.set("value", serializeObj(ctx, proto == null ? Values.NULL : proto));
protoDesc.set("writable", true);
protoDesc.set("enumerable", false);
protoDesc.set("configurable", false);
protoDesc.set("isOwn", true);
res.add(protoDesc);
ws.send(msg.respond(new JSONMap().set("result", res))); ws.send(msg.respond(new JSONMap().set("result", res)));
} }
@Override public void callFunctionOn(V8Message msg) { @Override public void callFunctionOn(V8Message msg) {
@ -667,36 +650,40 @@ public class SimpleDebugger implements Debugger {
else src = src.substring(0, start) + src.substring(end + 1); else src = src.substring(0, start) + src.substring(end + 1);
} }
switch (src) { try {
case CHROME_GET_PROP_FUNC: { switch (src) {
var path = JSON.parse(new Filename("tmp", "json"), (String)args.get(0)).list(); case CHROME_GET_PROP_FUNC: {
Object res = thisArg; var path = JSON.parse(null, (String)args.get(0)).list();
for (var el : path) res = Values.getMember(ctx, res, JSON.toJs(el)); Object res = thisArg;
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, res)))); for (var el : path) res = Values.getMember(ctx, res, JSON.toJs(el));
return; ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, res))));
return;
}
case VSCODE_STRINGIFY_VAL:
case VSCODE_STRINGIFY_PROPS:
case VSCODE_SHALLOW_COPY:
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, emptyObject))));
break;
case VSCODE_FLATTEN_ARRAY: {
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, thisArg))));
break;
}
case VSCODE_SYMBOL_REQUEST:
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, new ArrayValue(ctx)))));
break;
case VSCODE_CALL: {
var func = (FunctionValue)(args.size() < 1 ? null : args.get(0));
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, func.call(ctx, thisArg)))));
break;
}
default: {
var res = ctx.compile(new Filename("jscript", "eval"), src).call(ctx);
if (res instanceof FunctionValue) ((FunctionValue)res).call(ctx, thisArg, args);
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, res))));
}
} }
case VSCODE_STRINGIFY_VAL:
case VSCODE_STRINGIFY_PROPS:
case VSCODE_SHALLOW_COPY:
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, emptyObject))));
break;
case VSCODE_FLATTEN_ARRAY: {
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, thisArg))));
break;
}
case VSCODE_SYMBOL_REQUEST:
ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, new ArrayValue(ctx)))));
break;
case VSCODE_CALL: {
var func = (FunctionValue)(args.size() < 1 ? null : args.get(0));
try { ws.send(msg.respond(new JSONMap().set("result", serializeObj(ctx, func.call(ctx, thisArg))))); }
catch (EngineException e) { ws.send(msg.respond(new JSONMap().set("exceptionDetails", serializeException(ctx, e)))); }
break;
}
default:
ws.send(new V8Error("A non well-known function was used with callFunctionOn."));
break;
} }
catch (EngineException e) { ws.send(msg.respond(new JSONMap().set("exceptionDetails", serializeException(ctx, e)))); }
} }
@Override @Override
@ -708,8 +695,8 @@ public class SimpleDebugger implements Debugger {
int id = nextId(); int id = nextId();
var src = new Source(id, filename, source, locations); var src = new Source(id, filename, source, locations);
filenameToId.put(filename, id);
idToSource.put(id, src); idToSource.put(id, src);
filenameToId.put(filename, id);
for (var bpcd : idToBptCand.values()) { for (var bpcd : idToBptCand.values()) {
if (!bpcd.pattern.matcher(filename.toString()).matches()) continue; if (!bpcd.pattern.matcher(filename.toString()).matches()) continue;
@ -801,27 +788,18 @@ public class SimpleDebugger implements Debugger {
} }
@Override public void connect() { @Override public void connect() {
target.data.set(StackData.DEBUGGER, this); if (!target.attachDebugger(this)) {
ws.send(new V8Error("A debugger is already attached to this engine."));
}
} }
@Override public void disconnect() { @Override public void disconnect() {
target.data.remove(StackData.DEBUGGER); target.detachDebugger();
enabled = false; enabled = false;
updateNotifier.next(); updateNotifier.next();
} }
private SimpleDebugger(WebSocket ws, Engine target) { public SimpleDebugger(WebSocket ws, Engine target) {
this.ws = ws; this.ws = ws;
this.target = target; this.target = target;
} }
public static SimpleDebugger get(WebSocket ws, Engine target) {
if (target.data.has(StackData.DEBUGGER)) {
ws.send(new V8Error("A debugger is already attached to this engine."));
return null;
}
else {
var res = new SimpleDebugger(ws, target);
return res;
}
}
} }