mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Improvement of debugger plugin. Debugger itself became multithreaded
This commit is contained in:
parent
930d2087ab
commit
c490e2f9f8
|
@ -2,6 +2,9 @@ package org.teavm.chromerdp;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.codehaus.jackson.JsonNode;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.teavm.chromerdp.data.CallFrameDTO;
|
||||
|
@ -16,16 +19,21 @@ import org.teavm.debugging.*;
|
|||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeConsumer {
|
||||
private static final Object dummy = new Object();
|
||||
private ChromeRDPExchange exchange;
|
||||
private List<JavaScriptDebuggerListener> listeners = new ArrayList<>();
|
||||
private Set<RDPBreakpoint> breakpoints = new HashSet<>();
|
||||
private RDPCallFrame[] callStack = new RDPCallFrame[0];
|
||||
private Map<String, String> scripts = new HashMap<>();
|
||||
private Map<String, String> scriptIds = new HashMap<>();
|
||||
private ConcurrentMap<JavaScriptDebuggerListener, Object> listeners = new ConcurrentHashMap<>();
|
||||
private ConcurrentMap<RDPBreakpoint, Object> breakpoints = new ConcurrentHashMap<>();
|
||||
private volatile RDPCallFrame[] callStack = new RDPCallFrame[0];
|
||||
private ConcurrentMap<String, String> scripts = new ConcurrentHashMap<>();
|
||||
private ConcurrentMap<String, String> scriptIds = new ConcurrentHashMap<>();
|
||||
private boolean suspended = false;
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
private Map<Integer, ResponseHandler> responseHandlers = new HashMap<>();
|
||||
private int messageIdGenerator;
|
||||
private ConcurrentMap<Integer, ResponseHandler> responseHandlers = new ConcurrentHashMap<>();
|
||||
private AtomicInteger messageIdGenerator = new AtomicInteger();
|
||||
|
||||
private List<JavaScriptDebuggerListener> getListeners() {
|
||||
return new ArrayList<>(listeners.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExchange(ChromeRDPExchange exchange) {
|
||||
|
@ -37,15 +45,15 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
}
|
||||
this.exchange = exchange;
|
||||
if (exchange != null) {
|
||||
for (RDPBreakpoint breakpoint : breakpoints) {
|
||||
for (RDPBreakpoint breakpoint : breakpoints.keySet().toArray(new RDPBreakpoint[0])) {
|
||||
updateBreakpoint(breakpoint);
|
||||
}
|
||||
for (JavaScriptDebuggerListener listener : listeners) {
|
||||
for (JavaScriptDebuggerListener listener : getListeners()) {
|
||||
listener.attached();
|
||||
}
|
||||
} else {
|
||||
suspended = false;
|
||||
for (JavaScriptDebuggerListener listener : listeners) {
|
||||
for (JavaScriptDebuggerListener listener : getListeners()) {
|
||||
listener.detached();
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +94,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
callStack[i] = map(callFrameDTOs[i]);
|
||||
}
|
||||
this.callStack = callStack;
|
||||
for (JavaScriptDebuggerListener listener : listeners) {
|
||||
for (JavaScriptDebuggerListener listener : getListeners()) {
|
||||
listener.paused();
|
||||
}
|
||||
}
|
||||
|
@ -94,18 +102,17 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
private synchronized void fireResumed() {
|
||||
suspended = false;
|
||||
callStack = null;
|
||||
for (JavaScriptDebuggerListener listener : listeners) {
|
||||
for (JavaScriptDebuggerListener listener : getListeners()) {
|
||||
listener.resumed();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void scriptParsed(ScriptParsedNotification params) {
|
||||
if (scripts.containsKey(params.getScriptId())) {
|
||||
if (scripts.putIfAbsent(params.getScriptId(), params.getUrl()) != null) {
|
||||
return;
|
||||
}
|
||||
scripts.put(params.getScriptId(), params.getUrl());
|
||||
scriptIds.put(params.getUrl(), params.getScriptId());
|
||||
for (JavaScriptDebuggerListener listener : listeners) {
|
||||
for (JavaScriptDebuggerListener listener : getListeners()) {
|
||||
listener.scriptAdded(params.getUrl());
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +120,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
|
||||
@Override
|
||||
public void addListener(JavaScriptDebuggerListener listener) {
|
||||
listeners.add(listener);
|
||||
listeners.put(listener, dummy);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -194,23 +201,32 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
return exchange != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detach() {
|
||||
if (exchange != null) {
|
||||
exchange.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaScriptCallFrame[] getCallStack() {
|
||||
if (exchange == null) {
|
||||
return null;
|
||||
}
|
||||
JavaScriptCallFrame[] callStack = this.callStack;
|
||||
return callStack != null ? callStack.clone() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JavaScriptBreakpoint createBreakpoint(JavaScriptLocation location) {
|
||||
RDPBreakpoint breakpoint = new RDPBreakpoint(this, location);
|
||||
breakpoints.add(breakpoint);
|
||||
breakpoints.put(breakpoint, dummy);
|
||||
updateBreakpoint(breakpoint);
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
void destroyBreakpoint(RDPBreakpoint breakpoint) {
|
||||
breakpoints.remove(breakpoint);
|
||||
if (breakpoint.chromeId != null) {
|
||||
Message message = new Message();
|
||||
message.setMethod("Debugger.removeBreakpoint");
|
||||
|
@ -222,7 +238,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
}
|
||||
|
||||
void fireScriptAdded(String script) {
|
||||
for (JavaScriptDebuggerListener listener : listeners) {
|
||||
for (JavaScriptDebuggerListener listener : getListeners()) {
|
||||
listener.scriptAdded(script);
|
||||
}
|
||||
}
|
||||
|
@ -232,7 +248,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
return;
|
||||
}
|
||||
Message message = new Message();
|
||||
message.setId(++messageIdGenerator);
|
||||
message.setId(messageIdGenerator.incrementAndGet());
|
||||
message.setMethod("Debugger.setBreakpoint");
|
||||
SetBreakpointCommand params = new SetBreakpointCommand();
|
||||
params.setLocation(unmap(breakpoint.getLocation()));
|
||||
|
@ -241,7 +257,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
@Override public void received(JsonNode node) throws IOException {
|
||||
SetBreakpointResponse response = mapper.reader(SetBreakpointResponse.class).readValue(node);
|
||||
breakpoint.chromeId = response.getBreakpointId();
|
||||
for (JavaScriptDebuggerListener listener : listeners) {
|
||||
for (JavaScriptDebuggerListener listener : getListeners()) {
|
||||
listener.breakpointChanged(breakpoint);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,6 +52,15 @@ public class ChromeRDPDebuggerEndpoint implements ChromeRDPExchange {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect() {
|
||||
try {
|
||||
session.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@OnMessage
|
||||
public void receive(String message) throws IOException {
|
||||
for (ChromeRDPExchangeListener listener : listeners) {
|
||||
|
|
|
@ -7,6 +7,8 @@ package org.teavm.chromerdp;
|
|||
public interface ChromeRDPExchange {
|
||||
void send(String message);
|
||||
|
||||
void disconnect();
|
||||
|
||||
void addListener(ChromeRDPExchangeListener listener);
|
||||
|
||||
void removeListener(ChromeRDPExchangeListener listener);
|
||||
|
|
|
@ -48,6 +48,6 @@ public class RDPBreakpoint implements JavaScriptBreakpoint {
|
|||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return chromeId != null;
|
||||
return chromeId != null && debugger != null && debugger.isAttached();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import java.util.List;
|
|||
*/
|
||||
public class Breakpoint {
|
||||
private Debugger debugger;
|
||||
List<JavaScriptBreakpoint> jsBreakpoints = new ArrayList<>();
|
||||
volatile List<JavaScriptBreakpoint> jsBreakpoints = new ArrayList<>();
|
||||
private SourceLocation location;
|
||||
boolean valid;
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
package org.teavm.debugging;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
/**
|
||||
|
@ -25,16 +29,18 @@ import org.teavm.model.MethodReference;
|
|||
// TODO: variable name handling
|
||||
// TODO: class fields handling
|
||||
public class Debugger {
|
||||
private List<DebuggerListener> listeners = new ArrayList<>();
|
||||
private static final Object dummyObject = new Object();
|
||||
private ConcurrentMap<DebuggerListener, Object> listeners = new ConcurrentHashMap<>();
|
||||
private JavaScriptDebugger javaScriptDebugger;
|
||||
private DebugInformationProvider debugInformationProvider;
|
||||
private List<JavaScriptBreakpoint> temporaryJsBreakpoints = new ArrayList<>();
|
||||
private Map<String, DebugInformation> debugInformationMap = new HashMap<>();
|
||||
private Map<String, List<DebugInformation>> debugInformationFileMap = new HashMap<>();
|
||||
private Map<DebugInformation, String> scriptMap = new HashMap<>();
|
||||
Map<JavaScriptBreakpoint, Breakpoint> breakpointMap = new HashMap<>();
|
||||
Set<Breakpoint> breakpoints = new HashSet<>();
|
||||
private CallFrame[] callStack;
|
||||
private BlockingQueue<JavaScriptBreakpoint> temporaryBreakpoints = new LinkedBlockingQueue<>();
|
||||
private ConcurrentMap<String, DebugInformation> debugInformationMap = new ConcurrentHashMap<>();
|
||||
private ConcurrentMap<String, ConcurrentMap<DebugInformation, Object>> debugInformationFileMap =
|
||||
new ConcurrentHashMap<>();
|
||||
private ConcurrentMap<DebugInformation, String> scriptMap = new ConcurrentHashMap<>();
|
||||
ConcurrentMap<JavaScriptBreakpoint, Breakpoint> breakpointMap = new ConcurrentHashMap<>();
|
||||
ConcurrentMap<Breakpoint, Object> breakpoints = new ConcurrentHashMap<>();
|
||||
private volatile CallFrame[] callStack;
|
||||
|
||||
public Debugger(JavaScriptDebugger javaScriptDebugger, DebugInformationProvider debugInformationProvider) {
|
||||
this.javaScriptDebugger = javaScriptDebugger;
|
||||
|
@ -43,36 +49,36 @@ public class Debugger {
|
|||
}
|
||||
|
||||
public void addListener(DebuggerListener listener) {
|
||||
listeners.add(listener);
|
||||
listeners.put(listener, dummyObject);
|
||||
}
|
||||
|
||||
public void removeListener(DebuggerListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
public void suspend() {
|
||||
public synchronized void suspend() {
|
||||
javaScriptDebugger.suspend();
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
public synchronized void resume() {
|
||||
javaScriptDebugger.resume();
|
||||
}
|
||||
|
||||
public void stepInto() {
|
||||
public synchronized void stepInto() {
|
||||
javaScriptDebugger.stepInto();
|
||||
}
|
||||
|
||||
public void stepOut() {
|
||||
public synchronized void stepOut() {
|
||||
javaScriptDebugger.stepOut();
|
||||
}
|
||||
|
||||
public void stepOver() {
|
||||
public synchronized void stepOver() {
|
||||
javaScriptDebugger.stepOver();
|
||||
}
|
||||
|
||||
private List<DebugInformation> debugInformationBySource(String sourceFile) {
|
||||
List<DebugInformation> list = debugInformationFileMap.get(sourceFile);
|
||||
return list != null ? list : Collections.<DebugInformation>emptyList();
|
||||
Map<DebugInformation, Object> list = debugInformationFileMap.get(sourceFile);
|
||||
return list != null ? new ArrayList<>(list.keySet()) : Collections.<DebugInformation>emptyList();
|
||||
}
|
||||
|
||||
public void continueToLocation(SourceLocation location) {
|
||||
|
@ -90,7 +96,7 @@ public class Debugger {
|
|||
location.getLine(), location.getColumn());
|
||||
JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(jsLocation);
|
||||
if (jsBreakpoint != null) {
|
||||
temporaryJsBreakpoints.add(jsBreakpoint);
|
||||
temporaryBreakpoints.add(jsBreakpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,14 +113,14 @@ public class Debugger {
|
|||
|
||||
public Breakpoint createBreakpoint(SourceLocation location) {
|
||||
Breakpoint breakpoint = new Breakpoint(this, location);
|
||||
breakpoints.add(breakpoint);
|
||||
breakpoints.put(breakpoint, dummyObject);
|
||||
updateInternalBreakpoints(breakpoint);
|
||||
updateBreakpointStatus(breakpoint, false);
|
||||
return breakpoint;
|
||||
}
|
||||
|
||||
public Set<Breakpoint> getBreakpoints() {
|
||||
return new HashSet<>(breakpoints);
|
||||
return new HashSet<>(breakpoints.keySet());
|
||||
}
|
||||
|
||||
void updateInternalBreakpoints(Breakpoint breakpoint) {
|
||||
|
@ -122,7 +128,7 @@ public class Debugger {
|
|||
breakpointMap.remove(jsBreakpoint);
|
||||
jsBreakpoint.destroy();
|
||||
}
|
||||
breakpoint.jsBreakpoints.clear();
|
||||
List<JavaScriptBreakpoint> jsBreakpoints = new ArrayList<>();
|
||||
SourceLocation location = breakpoint.getLocation();
|
||||
for (DebugInformation debugInformation : debugInformationBySource(location.getFileName())) {
|
||||
Collection<GeneratedLocation> locations = debugInformation.getGeneratedLocations(location);
|
||||
|
@ -130,10 +136,15 @@ public class Debugger {
|
|||
JavaScriptLocation jsLocation = new JavaScriptLocation(scriptMap.get(debugInformation),
|
||||
genLocation.getLine(), genLocation.getColumn());
|
||||
JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(jsLocation);
|
||||
breakpoint.jsBreakpoints.add(jsBreakpoint);
|
||||
jsBreakpoints.add(jsBreakpoint);
|
||||
breakpointMap.put(jsBreakpoint, breakpoint);
|
||||
}
|
||||
}
|
||||
breakpoint.jsBreakpoints = jsBreakpoints;
|
||||
}
|
||||
|
||||
private DebuggerListener[] getListeners() {
|
||||
return listeners.keySet().toArray(new DebuggerListener[0]);
|
||||
}
|
||||
|
||||
void updateBreakpointStatus(Breakpoint breakpoint, boolean fireEvent) {
|
||||
|
@ -146,7 +157,7 @@ public class Debugger {
|
|||
if (breakpoint.valid != valid) {
|
||||
breakpoint.valid = valid;
|
||||
if (fireEvent) {
|
||||
for (DebuggerListener listener : listeners) {
|
||||
for (DebuggerListener listener : getListeners()) {
|
||||
listener.breakpointStatusChanged(breakpoint);
|
||||
}
|
||||
}
|
||||
|
@ -192,17 +203,23 @@ public class Debugger {
|
|||
if (debugInfo == null) {
|
||||
return;
|
||||
}
|
||||
debugInformationMap.put(name, debugInfo);
|
||||
for (String sourceFile : debugInfo.getCoveredSourceFiles()) {
|
||||
List<DebugInformation> list = debugInformationFileMap.get(sourceFile);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
debugInformationFileMap.put(sourceFile, list);
|
||||
if (debugInformationMap.putIfAbsent(name, debugInfo) != null) {
|
||||
return;
|
||||
}
|
||||
list.add(debugInfo);
|
||||
for (String sourceFile : debugInfo.getCoveredSourceFiles()) {
|
||||
ConcurrentMap<DebugInformation, Object> list = debugInformationFileMap.get(sourceFile);
|
||||
if (list == null) {
|
||||
list = new ConcurrentHashMap<>();
|
||||
ConcurrentMap<DebugInformation, Object> existing = debugInformationFileMap.putIfAbsent(
|
||||
sourceFile, list);
|
||||
if (existing != null) {
|
||||
list = existing;
|
||||
}
|
||||
}
|
||||
list.put(debugInfo, dummyObject);
|
||||
}
|
||||
scriptMap.put(debugInfo, name);
|
||||
for (Breakpoint breakpoint : breakpoints) {
|
||||
for (Breakpoint breakpoint : breakpoints.keySet()) {
|
||||
updateInternalBreakpoints(breakpoint);
|
||||
updateBreakpointStatus(breakpoint, true);
|
||||
}
|
||||
|
@ -212,40 +229,45 @@ public class Debugger {
|
|||
return javaScriptDebugger.isAttached();
|
||||
}
|
||||
|
||||
public void detach() {
|
||||
javaScriptDebugger.detach();
|
||||
}
|
||||
|
||||
void destroyBreakpoint(Breakpoint breakpoint) {
|
||||
for (JavaScriptBreakpoint jsBreakpoint : breakpoint.jsBreakpoints) {
|
||||
jsBreakpoint.destroy();
|
||||
breakpointMap.remove(jsBreakpoint);
|
||||
}
|
||||
breakpoint.jsBreakpoints.clear();
|
||||
breakpoint.jsBreakpoints = new ArrayList<>();
|
||||
breakpoints.remove(this);
|
||||
}
|
||||
|
||||
private void fireResumed() {
|
||||
for (JavaScriptBreakpoint jsBreakpoint : temporaryJsBreakpoints) {
|
||||
List<JavaScriptBreakpoint> termporaryBreakpoints = new ArrayList<>();
|
||||
this.temporaryBreakpoints.drainTo(termporaryBreakpoints);
|
||||
for (JavaScriptBreakpoint jsBreakpoint : temporaryBreakpoints) {
|
||||
jsBreakpoint.destroy();
|
||||
}
|
||||
temporaryJsBreakpoints.clear();
|
||||
for (DebuggerListener listener : listeners) {
|
||||
for (DebuggerListener listener : getListeners()) {
|
||||
listener.resumed();
|
||||
}
|
||||
}
|
||||
|
||||
private void fireAttached() {
|
||||
for (Breakpoint breakpoint : breakpoints) {
|
||||
for (Breakpoint breakpoint : breakpoints.keySet()) {
|
||||
updateInternalBreakpoints(breakpoint);
|
||||
updateBreakpointStatus(breakpoint, false);
|
||||
}
|
||||
for (DebuggerListener listener : listeners) {
|
||||
for (DebuggerListener listener : getListeners()) {
|
||||
listener.attached();
|
||||
}
|
||||
}
|
||||
|
||||
private void fireDetached() {
|
||||
for (Breakpoint breakpoint : breakpoints) {
|
||||
for (Breakpoint breakpoint : breakpoints.keySet()) {
|
||||
updateBreakpointStatus(breakpoint, false);
|
||||
}
|
||||
for (DebuggerListener listener : listeners) {
|
||||
for (DebuggerListener listener : getListeners()) {
|
||||
listener.detached();
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +288,7 @@ public class Debugger {
|
|||
@Override
|
||||
public void paused() {
|
||||
callStack = null;
|
||||
for (DebuggerListener listener : listeners) {
|
||||
for (DebuggerListener listener : getListeners()) {
|
||||
listener.paused();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@ public interface JavaScriptDebugger {
|
|||
|
||||
boolean isAttached();
|
||||
|
||||
void detach();
|
||||
|
||||
JavaScriptCallFrame[] getCallStack();
|
||||
|
||||
JavaScriptBreakpoint createBreakpoint(JavaScriptLocation location);
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.teavm.chromerdp.ChromeRDPServer;
|
|||
import org.teavm.debugging.Breakpoint;
|
||||
import org.teavm.debugging.Debugger;
|
||||
import org.teavm.debugging.DebuggerListener;
|
||||
import org.teavm.debugging.JavaScriptDebugger;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -23,6 +24,7 @@ import org.teavm.debugging.DebuggerListener;
|
|||
public class TeaVMDebugTarget implements IDebugTarget, IStep {
|
||||
ILaunch launch;
|
||||
Debugger teavmDebugger;
|
||||
JavaScriptDebugger jsDebugger;
|
||||
private ChromeRDPServer server;
|
||||
private boolean terminated;
|
||||
private TeaVMDebugProcess process;
|
||||
|
@ -90,6 +92,7 @@ public class TeaVMDebugTarget implements IDebugTarget, IStep {
|
|||
terminated = true;
|
||||
server.stop();
|
||||
fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
|
||||
fireEvent(new DebugEvent(thread, DebugEvent.TERMINATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -187,6 +190,7 @@ public class TeaVMDebugTarget implements IDebugTarget, IStep {
|
|||
|
||||
@Override
|
||||
public void disconnect() throws DebugException {
|
||||
teavmDebugger.detach();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
package org.teavm.eclipse.debugger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.eclipse.debug.core.ILaunchManager;
|
||||
import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.teavm.chromerdp.*;
|
||||
import org.teavm.chromerdp.ChromeRDPDebugger;
|
||||
import org.teavm.chromerdp.ChromeRDPServer;
|
||||
import org.teavm.debugging.Debugger;
|
||||
import org.teavm.debugging.URLDebugInformationProvider;
|
||||
|
||||
|
@ -29,64 +26,15 @@ public class TeaVMLaunchConfigurationDelegate implements ILaunchConfigurationDel
|
|||
final ChromeRDPServer server = new ChromeRDPServer();
|
||||
server.setPort(port);
|
||||
ChromeRDPDebugger jsDebugger = new ChromeRDPDebugger();
|
||||
server.setExchangeConsumer(new SynchronousMessageExchange(jsDebugger));
|
||||
server.setExchangeConsumer(jsDebugger);
|
||||
Debugger debugger = new Debugger(jsDebugger, new URLDebugInformationProvider(""));
|
||||
new Thread() {
|
||||
@Override public void run() {
|
||||
server.start();
|
||||
}
|
||||
}.start();
|
||||
launch.addDebugTarget(new TeaVMDebugTarget(launch, debugger, server));
|
||||
}
|
||||
|
||||
private static class SynchronousMessageExchange implements ChromeRDPExchangeConsumer,
|
||||
ChromeRDPExchange {
|
||||
private List<ChromeRDPExchangeListener> listeners = new ArrayList<>();
|
||||
private ChromeRDPDebugger debugger;
|
||||
private ChromeRDPExchange exchange;
|
||||
|
||||
public SynchronousMessageExchange(ChromeRDPDebugger debugger) {
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExchange(ChromeRDPExchange exchange) {
|
||||
this.exchange = exchange;
|
||||
debugger.setExchange(this);
|
||||
exchange.addListener(new ChromeRDPExchangeListener() {
|
||||
@Override public void received(final String message) throws IOException {
|
||||
postToUIThread(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void postToUIThread(final String message) {
|
||||
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
|
||||
@Override public void run() {
|
||||
try {
|
||||
for (ChromeRDPExchangeListener listener : listeners) {
|
||||
listener.received(message);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// TODO: add logging
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(String message) {
|
||||
exchange.send(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(ChromeRDPExchangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener(ChromeRDPExchangeListener listener) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
TeaVMDebugTarget target = new TeaVMDebugTarget(launch, debugger, server);
|
||||
launch.addDebugTarget(target);
|
||||
launch.addProcess(target.getProcess());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ public class TeaVMStackFrame implements IStackFrame {
|
|||
|
||||
@Override
|
||||
public boolean canResume() {
|
||||
return false;
|
||||
return thread.getTopStackFrame() == this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,11 +29,13 @@ public class TeaVMThread implements IThread {
|
|||
@Override
|
||||
public void resumed() {
|
||||
updateStackTrace();
|
||||
fireEvent(new DebugEvent(TeaVMThread.this, DebugEvent.RESUME));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paused() {
|
||||
updateStackTrace();
|
||||
fireEvent(new DebugEvent(TeaVMThread.this, DebugEvent.SUSPEND));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,16 +72,17 @@ public class TeaVMThread implements IThread {
|
|||
|
||||
@Override
|
||||
public boolean canTerminate() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTerminated() {
|
||||
return false;
|
||||
return debugTarget.isTerminated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void terminate() throws DebugException {
|
||||
debugTarget.terminate();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
|
@ -190,6 +193,6 @@ public class TeaVMThread implements IThread {
|
|||
|
||||
@Override
|
||||
public boolean hasStackFrames() throws DebugException {
|
||||
return true;
|
||||
return stackTrace != null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user