fix: clean up debugger API

This commit is contained in:
TopchetoEU 2023-12-27 20:02:45 +02:00
parent c0b895e00a
commit d5fd6e650e
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
13 changed files with 72 additions and 35 deletions

View File

@ -8,6 +8,7 @@ import java.nio.file.Path;
import me.topchetoeu.jscript.engine.Context;
import me.topchetoeu.jscript.engine.Engine;
import me.topchetoeu.jscript.engine.Environment;
import me.topchetoeu.jscript.engine.debug.DebugContext;
import me.topchetoeu.jscript.engine.debug.DebugServer;
import me.topchetoeu.jscript.engine.debug.SimpleDebugger;
import me.topchetoeu.jscript.engine.values.ArrayValue;
@ -46,7 +47,7 @@ public class Main {
}
static Thread engineTask, debugTask;
static Engine engine = new Engine(true);
static Engine engine = new Engine();
static DebugServer debugServer = new DebugServer();
static Environment environment = new Environment();
@ -133,7 +134,10 @@ public class Main {
environment.add(ModuleRepo.ENV_KEY, ModuleRepo.ofFilesystem(fs));
}
private static void initEngine() {
debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws, engine));
var ctx = new DebugContext();
// engine.globalEnvironment.add(DebugContext.ENV_KEY, ctx);
debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws).attach(ctx));
engineTask = engine.start();
debugTask = debugServer.start(new InetSocketAddress("127.0.0.1", 9229), true);
}

View File

@ -94,7 +94,7 @@ public class Context implements Extensions {
private Context curr = self;
private void update() {
while (curr.frame == null && curr != null) curr = curr.parent;
while (curr != null && curr.frame == null) curr = curr.parent;
}
@Override public boolean hasNext() {

View File

@ -57,7 +57,6 @@ public class Engine {
public final Environment globalEnvironment = new Environment();
public final int id = ++nextId;
public final boolean debugging;
public int maxStackFrames = 10000;
private Thread thread;
@ -111,7 +110,6 @@ public class Engine {
return pushMsg(micro, env, new UncompiledFunction(filename, raw), thisArg, args);
}
public Engine(boolean debugging) {
this.debugging = debugging;
public Engine() {
}
}

View File

@ -25,9 +25,6 @@ public interface DebugHandler {
void getProperties(V8Message msg);
void releaseObjectGroup(V8Message msg);
void releaseObject(V8Message msg);
/**
* This method might not execute the actual code for well-known requests
*/
void callFunctionOn(V8Message msg);
void runtimeEnable(V8Message msg);

View File

@ -50,8 +50,6 @@ public class DebugServer {
private void handle(WebSocket ws, Debugger debugger) {
WebSocketMessage raw;
debugger.connect();
while ((raw = ws.receive()) != null) {
if (raw.type != Type.Text) {
ws.send(new V8Error("Expected a text message."));
@ -72,8 +70,9 @@ public class DebugServer {
switch (msg.name) {
case "Debugger.enable":
connNotifier.next();
debugger.enable(msg); continue;
case "Debugger.disable": debugger.disable(msg); continue;
debugger.enable(msg);
continue;
case "Debugger.disable": debugger.close(); continue;
case "Debugger.setBreakpointByUrl": debugger.setBreakpointByUrl(msg); continue;
case "Debugger.removeBreakpoint": debugger.removeBreakpoint(msg); continue;
@ -116,7 +115,7 @@ public class DebugServer {
}
}
debugger.disconnect();
debugger.close();
}
private void onWsConnect(HttpRequest req, Socket socket, DebuggerProvider debuggerProvider) {
var key = req.headers.get("sec-websocket-key");
@ -151,7 +150,7 @@ public class DebugServer {
catch (RuntimeException e) {
ws.send(new V8Error(e.getMessage()));
}
finally { ws.close(); debugger.disconnect(); }
finally { ws.close(); debugger.close(); }
}, "Debug Handler");
}

View File

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

View File

@ -174,7 +174,6 @@ public class SimpleDebugger implements Debugger {
public State state = State.RESUMED;
public final WebSocket ws;
public final Engine target;
private ObjectValue emptyObject = new ObjectValue();
@ -477,7 +476,7 @@ public class SimpleDebugger implements Debugger {
private RunResult run(Frame codeFrame, String code) {
if (codeFrame == null) return new RunResult(null, code, new EngineException("Invalid code frame!"));
var engine = new Engine(false);
var engine = new Engine();
var env = codeFrame.func.environment.fork();
env.global = new GlobalScope(codeFrame.local);
@ -574,8 +573,36 @@ public class SimpleDebugger implements Debugger {
updateNotifier.next();
}
@Override public synchronized void disable(V8Message msg) {
enabled = false;
close();
ws.send(msg.respond());
}
public synchronized void close() {
enabled = false;
execptionType = CatchType.NONE;
state = State.RESUMED;
idToBptCand.clear();
idToBreakpoint.clear();
locToBreakpoint.clear();
tmpBreakpts.clear();
filenameToId.clear();
idToSource.clear();
pendingSources.clear();
idToFrame.clear();
codeFrameToFrame.clear();
idToObject.clear();
objectToId.clear();
objectGroups.clear();
pendingPause = false;
stepOutFrame = currFrame = null;
stepOutPtr = 0;
updateNotifier.next();
}
@ -952,19 +979,12 @@ public class SimpleDebugger implements Debugger {
}
}
@Override public synchronized void connect() {
if (!DebugContext.get(target.globalEnvironment).attachDebugger(this)) {
ws.send(new V8Error("A debugger is already attached to this engine."));
}
}
@Override public synchronized void disconnect() {
DebugContext.get(target.globalEnvironment).detachDebugger();
enabled = false;
updateNotifier.next();
public SimpleDebugger attach(DebugContext ctx) {
ctx.attachDebugger(this);
return this;
}
public SimpleDebugger(WebSocket ws, Engine target) {
public SimpleDebugger(WebSocket ws) {
this.ws = ws;
this.target = target;
}
}

View File

@ -303,6 +303,13 @@ public class CodeFrame {
return Runners.NO_RETURN;
}
public void onPush() {
DebugContext.get(ctx).onFramePush(ctx, this);
}
public void onPop() {
DebugContext.get(ctx.parent).onFramePop(ctx.parent, 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

@ -33,11 +33,18 @@ public class CodeFunction extends FunctionValue {
public Object call(Context ctx, Object thisArg, Object ...args) {
var frame = new CodeFrame(ctx, thisArg, args, this);
frame.onPush();
try {
while (true) {
var res = frame.next(Runners.NO_RETURN, Runners.NO_RETURN, null);
if (res != Runners.NO_RETURN) return res;
}
}
finally {
frame.onPop();
}
}
public CodeFunction(Environment environment, String name, FunctionBody body, ValueVariable... captures) {
super(name, body.argsN);

View File

@ -21,6 +21,7 @@ import me.topchetoeu.jscript.interop.Native;
private void next(Context ctx, Object inducedValue, Object inducedError) {
Object res = null;
frame.onPush();
awaiting = false;
while (!awaiting) {
try {
@ -36,6 +37,7 @@ import me.topchetoeu.jscript.interop.Native;
break;
}
}
frame.onPop();
if (awaiting) {
PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject));

View File

@ -30,6 +30,7 @@ import me.topchetoeu.jscript.interop.Native;
Object res = null;
state = 0;
frame.onPush();
while (state == 0) {
try {
res = frame.next(inducedValue, inducedReturn, inducedError == Runners.NO_RETURN ? null : new EngineException(inducedError));
@ -47,6 +48,7 @@ import me.topchetoeu.jscript.interop.Native;
break;
}
}
frame.onPop();
if (state == 1) {
PromiseLib.then(ctx, frame.pop(), new NativeFunction(this::fulfill), new NativeFunction(this::reject));

View File

@ -26,6 +26,7 @@ import me.topchetoeu.jscript.interop.Native;
Object res = null;
yielding = false;
frame.onPush();
while (!yielding) {
try {
res = frame.next(inducedValue, inducedReturn, inducedError == Runners.NO_RETURN ? null : new EngineException(inducedError));
@ -40,6 +41,7 @@ import me.topchetoeu.jscript.interop.Native;
throw e;
}
}
frame.onPop();
if (done) frame = null;
else res = frame.pop();