mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Refactor Debugger interface for attaching/detaching. Fix bugs with line
mapping generation
This commit is contained in:
parent
81fff7a4a6
commit
f6853eda80
|
@ -0,0 +1,143 @@
|
||||||
|
package org.teavm.chromerpd;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.teavm.debugging.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
|
*/
|
||||||
|
public class ChromeRDPDebugger implements JavaScriptDebugger {
|
||||||
|
private ChromeRDPDebuggerEndpoint endpoint;
|
||||||
|
private List<JavaScriptDebuggerListener> listeners = new ArrayList<>();
|
||||||
|
private Set<RDPBreakpoint> breakpoints = new HashSet<>();
|
||||||
|
|
||||||
|
void setEndpoint(ChromeRDPDebuggerEndpoint endpoint) {
|
||||||
|
if (this.endpoint == endpoint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
if (endpoint != null) {
|
||||||
|
for (RDPBreakpoint breakpoint : breakpoints) {
|
||||||
|
endpoint.updateBreakpoint(breakpoint);
|
||||||
|
}
|
||||||
|
for (JavaScriptDebuggerListener listener : listeners) {
|
||||||
|
listener.attached();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (JavaScriptDebuggerListener listener : listeners) {
|
||||||
|
listener.detached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(JavaScriptDebuggerListener listener) {
|
||||||
|
listeners.add(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeListener(JavaScriptDebuggerListener listener) {
|
||||||
|
listeners.remove(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void suspend() {
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint.suspend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resume() {
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint.resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stepInto() {
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint.stepInto();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stepOut() {
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint.stepOut();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stepOver() {
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint.stepOver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void continueToLocation(JavaScriptLocation location) {
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint.continueToLocation(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSuspended() {
|
||||||
|
return endpoint != null && endpoint.isSuspended();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAttached() {
|
||||||
|
return endpoint != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaScriptCallFrame[] getCallStack() {
|
||||||
|
return endpoint != null ? endpoint.getCallStack() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaScriptBreakpoint getCurrentBreakpoint() {
|
||||||
|
return endpoint != null ? endpoint.getCurrentBreakpoint() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JavaScriptBreakpoint createBreakpoint(JavaScriptLocation location) {
|
||||||
|
RDPBreakpoint breakpoint = new RDPBreakpoint(this, location);
|
||||||
|
breakpoints.add(breakpoint);
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint.updateBreakpoint(breakpoint);
|
||||||
|
}
|
||||||
|
return breakpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyBreakpoint(RDPBreakpoint breakpoint) {
|
||||||
|
breakpoints.remove(breakpoint);
|
||||||
|
if (endpoint != null) {
|
||||||
|
endpoint.destroyBreakpoint(breakpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fireResumed() {
|
||||||
|
for (JavaScriptDebuggerListener listener : listeners) {
|
||||||
|
listener.resumed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void firePaused() {
|
||||||
|
for (JavaScriptDebuggerListener listener : listeners) {
|
||||||
|
listener.paused();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fireScriptAdded(String script) {
|
||||||
|
for (JavaScriptDebuggerListener listener : listeners) {
|
||||||
|
listener.scriptAdded(script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,14 +16,9 @@
|
||||||
package org.teavm.chromerpd;
|
package org.teavm.chromerpd;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.websocket.OnClose;
|
import javax.websocket.*;
|
||||||
import javax.websocket.OnMessage;
|
|
||||||
import javax.websocket.OnOpen;
|
|
||||||
import javax.websocket.Session;
|
|
||||||
import javax.websocket.server.ServerEndpoint;
|
import javax.websocket.server.ServerEndpoint;
|
||||||
import org.codehaus.jackson.JsonNode;
|
import org.codehaus.jackson.JsonNode;
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
|
@ -39,8 +34,7 @@ import org.teavm.debugging.*;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
@ServerEndpoint("/")
|
@ServerEndpoint("/")
|
||||||
public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
public class ChromeRDPDebuggerEndpoint {
|
||||||
private List<JavaScriptDebuggerListener> listeners = new ArrayList<>();
|
|
||||||
private Session session;
|
private Session session;
|
||||||
private RDPCallFrame[] callStack = new RDPCallFrame[0];
|
private RDPCallFrame[] callStack = new RDPCallFrame[0];
|
||||||
private Map<String, String> scripts = new HashMap<>();
|
private Map<String, String> scripts = new HashMap<>();
|
||||||
|
@ -50,24 +44,24 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
private Map<Integer, Deferred> deferredResponses = new HashMap<>();
|
private Map<Integer, Deferred> deferredResponses = new HashMap<>();
|
||||||
private int messageIdGenerator;
|
private int messageIdGenerator;
|
||||||
boolean closed;
|
boolean closed;
|
||||||
private ChromeRDPContainer container;
|
private ChromeRDPDebugger debugger;
|
||||||
|
|
||||||
@OnOpen
|
@OnOpen
|
||||||
public void open(Session session) {
|
public void open(Session session) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
Object container = session.getUserProperties().get("rdp.container");
|
Object debugger = session.getUserProperties().get("chrome.rdp");
|
||||||
if (container instanceof ChromeRDPContainer) {
|
if (debugger instanceof ChromeRDPDebugger) {
|
||||||
this.container = (ChromeRDPContainer)container;
|
this.debugger = (ChromeRDPDebugger)debugger;
|
||||||
this.container.setDebugger(this);
|
this.debugger.setEndpoint(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClose
|
@OnClose
|
||||||
public void close() {
|
public void close() {
|
||||||
closed = true;
|
closed = true;
|
||||||
if (this.container != null) {
|
if (this.debugger != null) {
|
||||||
this.container.setDebugger(null);
|
this.debugger.setEndpoint(null);
|
||||||
this.container = null;
|
this.debugger = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +98,7 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
for (int i = 0; i < callFrames.length; ++i) {
|
for (int i = 0; i < callFrames.length; ++i) {
|
||||||
callFrames[i] = map(callFrameDTOs[i]);
|
callFrames[i] = map(callFrameDTOs[i]);
|
||||||
}
|
}
|
||||||
for (JavaScriptDebuggerListener listener : listeners) {
|
debugger.firePaused();
|
||||||
listener.paused();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RDPCallFrame map(CallFrameDTO dto) {
|
RDPCallFrame map(CallFrameDTO dto) {
|
||||||
|
@ -127,9 +119,7 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
|
|
||||||
private void fireResumed() {
|
private void fireResumed() {
|
||||||
suspended = false;
|
suspended = false;
|
||||||
for (JavaScriptDebuggerListener listener : listeners) {
|
debugger.fireResumed();
|
||||||
listener.resumed();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scriptParsed(ScriptParsedNotification params) {
|
private void scriptParsed(ScriptParsedNotification params) {
|
||||||
|
@ -138,19 +128,7 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
}
|
}
|
||||||
scripts.put(params.getScriptId(), params.getUrl());
|
scripts.put(params.getScriptId(), params.getUrl());
|
||||||
scriptIds.put(params.getUrl(), params.getScriptId());
|
scriptIds.put(params.getUrl(), params.getScriptId());
|
||||||
for (JavaScriptDebuggerListener listener : listeners) {
|
debugger.fireScriptAdded(params.getUrl());
|
||||||
listener.scriptAdded(params.getUrl());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addListener(JavaScriptDebuggerListener listener) {
|
|
||||||
listeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeListener(JavaScriptDebuggerListener listener) {
|
|
||||||
listeners.remove(listener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendMessage(Message message) {
|
private void sendMessage(Message message) {
|
||||||
|
@ -165,7 +143,6 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void suspend() {
|
public void suspend() {
|
||||||
if (closed) {
|
if (closed) {
|
||||||
return;
|
return;
|
||||||
|
@ -175,7 +152,6 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resume() {
|
public void resume() {
|
||||||
if (closed) {
|
if (closed) {
|
||||||
return;
|
return;
|
||||||
|
@ -185,7 +161,6 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stepInto() {
|
public void stepInto() {
|
||||||
if (closed) {
|
if (closed) {
|
||||||
return;
|
return;
|
||||||
|
@ -195,7 +170,6 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stepOut() {
|
public void stepOut() {
|
||||||
if (closed) {
|
if (closed) {
|
||||||
return;
|
return;
|
||||||
|
@ -205,7 +179,6 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stepOver() {
|
public void stepOver() {
|
||||||
if (closed) {
|
if (closed) {
|
||||||
return;
|
return;
|
||||||
|
@ -215,7 +188,6 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void continueToLocation(JavaScriptLocation location) {
|
public void continueToLocation(JavaScriptLocation location) {
|
||||||
Message message = new Message();
|
Message message = new Message();
|
||||||
message.setMethod("Debugger.continueToLocation");
|
message.setMethod("Debugger.continueToLocation");
|
||||||
|
@ -225,28 +197,24 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
sendMessage(message);
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSuspended() {
|
public boolean isSuspended() {
|
||||||
return suspended;
|
return suspended;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaScriptCallFrame[] getCallStack() {
|
public JavaScriptCallFrame[] getCallStack() {
|
||||||
return callStack;
|
return callStack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public JavaScriptBreakpoint getCurrentBreakpoint() {
|
public JavaScriptBreakpoint getCurrentBreakpoint() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void updateBreakpoint(RDPBreakpoint breakpoint) {
|
||||||
public JavaScriptBreakpoint createBreakpoint(JavaScriptLocation location) {
|
|
||||||
Message message = new Message();
|
Message message = new Message();
|
||||||
message.setId(messageIdGenerator++);
|
message.setId(messageIdGenerator++);
|
||||||
message.setMethod("Debugger.setBreakpoint");
|
message.setMethod("Debugger.setBreakpoint");
|
||||||
SetBreakpointCommand params = new SetBreakpointCommand();
|
SetBreakpointCommand params = new SetBreakpointCommand();
|
||||||
params.setLocation(unmap(location));
|
params.setLocation(unmap(breakpoint.getLocation()));
|
||||||
message.setParams(mapper.valueToTree(params));
|
message.setParams(mapper.valueToTree(params));
|
||||||
Deferred deferred = new Deferred();
|
Deferred deferred = new Deferred();
|
||||||
deferredResponses.put(message.getId(), deferred);
|
deferredResponses.put(message.getId(), deferred);
|
||||||
|
@ -254,18 +222,20 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
|
||||||
try {
|
try {
|
||||||
SetBreakpointResponse response = mapper.reader(SetBreakpointResponse.class)
|
SetBreakpointResponse response = mapper.reader(SetBreakpointResponse.class)
|
||||||
.readValue((JsonNode)deferred.get());
|
.readValue((JsonNode)deferred.get());
|
||||||
return new RDPBreakpoint(response.getBreakpointId(), this, map(response.getActualLocation()));
|
breakpoint.chromeId = response.getBreakpointId();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyBreakpoint(RDPBreakpoint breakpoint) {
|
void destroyBreakpoint(RDPBreakpoint breakpoint) {
|
||||||
Message message = new Message();
|
if (breakpoint.chromeId != null) {
|
||||||
message.setMethod("Debugger.removeBreakpoint");
|
Message message = new Message();
|
||||||
RemoveBreakpointCommand params = new RemoveBreakpointCommand();
|
message.setMethod("Debugger.removeBreakpoint");
|
||||||
params.setBreakpointId(breakpoint.getChromeId());
|
RemoveBreakpointCommand params = new RemoveBreakpointCommand();
|
||||||
message.setParams(mapper.valueToTree(params));
|
params.setBreakpointId(breakpoint.chromeId);
|
||||||
sendMessage(message);
|
message.setParams(mapper.valueToTree(params));
|
||||||
|
sendMessage(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package org.teavm.chromerpd;
|
package org.teavm.chromerpd;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import javax.websocket.Decoder;
|
import javax.websocket.Decoder;
|
||||||
import javax.websocket.Encoder;
|
import javax.websocket.Encoder;
|
||||||
import javax.websocket.Extension;
|
import javax.websocket.Extension;
|
||||||
|
@ -35,8 +34,7 @@ import org.teavm.debugging.JavaScriptDebugger;
|
||||||
public class ChromeRDPServer {
|
public class ChromeRDPServer {
|
||||||
private int port = 2357;
|
private int port = 2357;
|
||||||
private Appendable output = System.err;
|
private Appendable output = System.err;
|
||||||
private AtomicReference<JavaScriptDebugger> debugger = new AtomicReference<>();
|
private ChromeRDPDebugger debugger = new ChromeRDPDebugger();
|
||||||
private List<ChromeRDPServerListener> listeners = new ArrayList<>();
|
|
||||||
|
|
||||||
public int getPort() {
|
public int getPort() {
|
||||||
return port;
|
return port;
|
||||||
|
@ -54,14 +52,6 @@ public class ChromeRDPServer {
|
||||||
this.output = output;
|
this.output = output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addListener(ChromeRDPServerListener listener) {
|
|
||||||
listeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeListener(ChromeRDPServerListener listener) {
|
|
||||||
listeners.remove(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
final Server server = new Server();
|
final Server server = new Server();
|
||||||
ServerConnector connector = new ServerConnector(server);
|
ServerConnector connector = new ServerConnector(server);
|
||||||
|
@ -88,11 +78,7 @@ public class ChromeRDPServer {
|
||||||
private Map<String, Object> userProperties = new HashMap<>();
|
private Map<String, Object> userProperties = new HashMap<>();
|
||||||
|
|
||||||
public RPDEndpointConfig() {
|
public RPDEndpointConfig() {
|
||||||
userProperties.put("rdp.container", new ChromeRDPContainer() {
|
userProperties.put("chrome.rdp", debugger);
|
||||||
@Override public void setDebugger(ChromeRDPDebuggerEndpoint debugger) {
|
|
||||||
ChromeRDPServer.this.setDebugger(debugger);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -137,19 +123,6 @@ public class ChromeRDPServer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public JavaScriptDebugger getDebugger() {
|
public JavaScriptDebugger getDebugger() {
|
||||||
return debugger.get();
|
return debugger;
|
||||||
}
|
|
||||||
|
|
||||||
void setDebugger(JavaScriptDebugger debugger) {
|
|
||||||
if (debugger != null) {
|
|
||||||
if (!this.debugger.compareAndSet(null, debugger)) {
|
|
||||||
throw new IllegalStateException("Can't handle more than one connection");
|
|
||||||
}
|
|
||||||
for (ChromeRDPServerListener listener : listeners) {
|
|
||||||
listener.connected(this);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.debugger.set(null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2014 Alexey Andreev.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
package org.teavm.chromerpd;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public interface ChromeRDPServerListener {
|
|
||||||
void connected(ChromeRDPServer server);
|
|
||||||
}
|
|
|
@ -23,20 +23,15 @@ import org.teavm.debugging.JavaScriptLocation;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class RDPBreakpoint implements JavaScriptBreakpoint {
|
public class RDPBreakpoint implements JavaScriptBreakpoint {
|
||||||
private String chromeId;
|
String chromeId;
|
||||||
private ChromeRDPDebuggerEndpoint debugger;
|
private ChromeRDPDebugger debugger;
|
||||||
private JavaScriptLocation location;
|
private JavaScriptLocation location;
|
||||||
|
|
||||||
public RDPBreakpoint(String chromeId, ChromeRDPDebuggerEndpoint debugger, JavaScriptLocation location) {
|
RDPBreakpoint(ChromeRDPDebugger debugger, JavaScriptLocation location) {
|
||||||
this.chromeId = chromeId;
|
|
||||||
this.debugger = debugger;
|
this.debugger = debugger;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getChromeId() {
|
|
||||||
return chromeId;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JavaScriptLocation getLocation() {
|
public JavaScriptLocation getLocation() {
|
||||||
return location;
|
return location;
|
||||||
|
@ -44,8 +39,14 @@ public class RDPBreakpoint implements JavaScriptBreakpoint {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
if (!debugger.closed) {
|
if (debugger != null) {
|
||||||
debugger.destroyBreakpoint(this);
|
debugger.destroyBreakpoint(this);
|
||||||
|
debugger = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": ["main.js"],
|
"scripts": ["main.js"]
|
||||||
"persistent": false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -169,6 +169,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
if (!minified) {
|
if (!minified) {
|
||||||
innerWriter.append('\n');
|
innerWriter.append('\n');
|
||||||
column = 0;
|
column = 0;
|
||||||
|
++line;
|
||||||
lineStart = true;
|
lineStart = true;
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.debugging;
|
package org.teavm.debugging;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,16 +24,13 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class Breakpoint {
|
public class Breakpoint {
|
||||||
private Debugger debugger;
|
private Debugger debugger;
|
||||||
private List<JavaScriptBreakpoint> jsBreakpoints;
|
List<JavaScriptBreakpoint> jsBreakpoints = new ArrayList<>();
|
||||||
private SourceLocation location;
|
private SourceLocation location;
|
||||||
|
boolean valid;
|
||||||
|
|
||||||
Breakpoint(Debugger debugger, List<JavaScriptBreakpoint> jsBreakpoints, SourceLocation location) {
|
Breakpoint(Debugger debugger, SourceLocation location) {
|
||||||
this.debugger = debugger;
|
this.debugger = debugger;
|
||||||
this.jsBreakpoints = jsBreakpoints;
|
|
||||||
this.location = location;
|
this.location = location;
|
||||||
for (JavaScriptBreakpoint jsBreakpoint : jsBreakpoints) {
|
|
||||||
debugger.breakpointMap.put(jsBreakpoint, this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceLocation getLocation() {
|
public SourceLocation getLocation() {
|
||||||
|
@ -44,11 +42,17 @@ public class Breakpoint {
|
||||||
jsBreakpoint.destroy();
|
jsBreakpoint.destroy();
|
||||||
debugger.breakpointMap.remove(jsBreakpoint);
|
debugger.breakpointMap.remove(jsBreakpoint);
|
||||||
}
|
}
|
||||||
|
debugger.breakpoints.remove(this);
|
||||||
jsBreakpoints.clear();
|
jsBreakpoints.clear();
|
||||||
|
debugger = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValid() {
|
||||||
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDestroyed() {
|
public boolean isDestroyed() {
|
||||||
return jsBreakpoints.isEmpty();
|
return debugger == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Debugger getDebugger() {
|
public Debugger getDebugger() {
|
||||||
|
|
|
@ -203,8 +203,8 @@ public class DebugInformation {
|
||||||
ensureLine(sourceLine);
|
ensureLine(sourceLine);
|
||||||
generatedLocationSize.set(sourceLine, generatedLocationSize.get(sourceLine) + 1);
|
generatedLocationSize.set(sourceLine, generatedLocationSize.get(sourceLine) + 1);
|
||||||
int slot = generatedLocationStart.get(sourceLine);
|
int slot = generatedLocationStart.get(sourceLine);
|
||||||
slot = addData(slot, column);
|
|
||||||
slot = addData(slot, line);
|
slot = addData(slot, line);
|
||||||
|
slot = addData(slot, column);
|
||||||
generatedLocationStart.set(sourceLine, slot);
|
generatedLocationStart.set(sourceLine, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,13 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
||||||
IntegerArray values = new IntegerArray(1);
|
IntegerArray values = new IntegerArray(1);
|
||||||
|
|
||||||
public void add(LocationProvider location, int value) {
|
public void add(LocationProvider location, int value) {
|
||||||
|
if (lines.size() > 1) {
|
||||||
|
int last = lines.size() - 1;
|
||||||
|
if (lines.get(last) == location.getLine() && columns.get(last) == location.getColumn()) {
|
||||||
|
values.set(last, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
lines.add(location.getLine());
|
lines.add(location.getLine());
|
||||||
columns.add(location.getColumn());
|
columns.add(location.getColumn());
|
||||||
values.add(value);
|
values.add(value);
|
||||||
|
|
|
@ -41,6 +41,7 @@ class DebugInformationReader {
|
||||||
debugInfo.classMapping = readMapping();
|
debugInfo.classMapping = readMapping();
|
||||||
debugInfo.methodMapping = readMapping();
|
debugInfo.methodMapping = readMapping();
|
||||||
debugInfo.rebuildFileDescriptions();
|
debugInfo.rebuildFileDescriptions();
|
||||||
|
debugInfo.rebuildMaps();
|
||||||
return debugInfo;
|
return debugInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,9 @@ class DebugInformationWriter {
|
||||||
int[] lines = mapping.lines.clone();
|
int[] lines = mapping.lines.clone();
|
||||||
int last = 0;
|
int last = 0;
|
||||||
for (int i = 0; i < lines.length; ++i) {
|
for (int i = 0; i < lines.length; ++i) {
|
||||||
last = lines[i];
|
int next = lines[i];
|
||||||
lines[i] -= last;
|
lines[i] -= last;
|
||||||
|
last = next;
|
||||||
}
|
}
|
||||||
writeRle(lines);
|
writeRle(lines);
|
||||||
resetRelativeNumber();
|
resetRelativeNumber();
|
||||||
|
|
|
@ -33,6 +33,7 @@ public class Debugger {
|
||||||
private Map<String, List<DebugInformation>> debugInformationFileMap = new HashMap<>();
|
private Map<String, List<DebugInformation>> debugInformationFileMap = new HashMap<>();
|
||||||
private Map<DebugInformation, String> scriptMap = new HashMap<>();
|
private Map<DebugInformation, String> scriptMap = new HashMap<>();
|
||||||
Map<JavaScriptBreakpoint, Breakpoint> breakpointMap = new HashMap<>();
|
Map<JavaScriptBreakpoint, Breakpoint> breakpointMap = new HashMap<>();
|
||||||
|
Set<Breakpoint> breakpoints = new HashSet<>();
|
||||||
private CallFrame[] callStack;
|
private CallFrame[] callStack;
|
||||||
|
|
||||||
public Debugger(JavaScriptDebugger javaScriptDebugger, DebugInformationProvider debugInformationProvider) {
|
public Debugger(JavaScriptDebugger javaScriptDebugger, DebugInformationProvider debugInformationProvider) {
|
||||||
|
@ -58,23 +59,14 @@ public class Debugger {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stepInto() {
|
public void stepInto() {
|
||||||
if (!javaScriptDebugger.isSuspended()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
javaScriptDebugger.stepInto();
|
javaScriptDebugger.stepInto();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stepOut() {
|
public void stepOut() {
|
||||||
if (!javaScriptDebugger.isSuspended()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
javaScriptDebugger.stepOut();
|
javaScriptDebugger.stepOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stepOver() {
|
public void stepOver() {
|
||||||
if (!javaScriptDebugger.isSuspended()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
javaScriptDebugger.stepOver();
|
javaScriptDebugger.stepOver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,19 +106,49 @@ public class Debugger {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Breakpoint createBreakpoint(SourceLocation location) {
|
public Breakpoint createBreakpoint(SourceLocation location) {
|
||||||
List<JavaScriptBreakpoint> jsBreakpoints = new ArrayList<>();
|
Breakpoint breakpoint = new Breakpoint(this, location);
|
||||||
|
breakpoints.add(breakpoint);
|
||||||
|
updateInternalBreakpoints(breakpoint);
|
||||||
|
updateBreakpointStatus(breakpoint, false);
|
||||||
|
return breakpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Breakpoint> getBreakpoints() {
|
||||||
|
return Collections.unmodifiableSet(breakpoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateInternalBreakpoints(Breakpoint breakpoint) {
|
||||||
|
for (JavaScriptBreakpoint jsBreakpoint : breakpoint.jsBreakpoints) {
|
||||||
|
breakpointMap.remove(jsBreakpoint);
|
||||||
|
jsBreakpoint.destroy();
|
||||||
|
}
|
||||||
|
SourceLocation location = breakpoint.getLocation();
|
||||||
for (DebugInformation debugInformation : debugInformationBySource(location.getFileName())) {
|
for (DebugInformation debugInformation : debugInformationBySource(location.getFileName())) {
|
||||||
Collection<GeneratedLocation> locations = debugInformation.getGeneratedLocations(location);
|
Collection<GeneratedLocation> locations = debugInformation.getGeneratedLocations(location);
|
||||||
for (GeneratedLocation genLocation : locations) {
|
for (GeneratedLocation genLocation : locations) {
|
||||||
JavaScriptLocation jsLocation = new JavaScriptLocation(scriptMap.get(debugInformation),
|
JavaScriptLocation jsLocation = new JavaScriptLocation(scriptMap.get(debugInformation),
|
||||||
genLocation.getLine(), genLocation.getColumn());
|
genLocation.getLine(), genLocation.getColumn());
|
||||||
JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(jsLocation);
|
JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(jsLocation);
|
||||||
if (jsBreakpoint != null) {
|
breakpoint.jsBreakpoints.add(jsBreakpoint);
|
||||||
jsBreakpoints.add(jsBreakpoint);
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBreakpointStatus(Breakpoint breakpoint, boolean fireEvent) {
|
||||||
|
boolean valid = false;
|
||||||
|
for (JavaScriptBreakpoint jsBreakpoint : breakpoint.jsBreakpoints) {
|
||||||
|
if (jsBreakpoint.isValid()) {
|
||||||
|
valid = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (breakpoint.valid != valid) {
|
||||||
|
breakpoint.valid = valid;
|
||||||
|
if (fireEvent) {
|
||||||
|
for (DebuggerListener listener : listeners) {
|
||||||
|
listener.breakpointStatusChanged(breakpoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !jsBreakpoints.isEmpty() ? new Breakpoint(this, jsBreakpoints, location) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CallFrame[] getCallStack() {
|
public CallFrame[] getCallStack() {
|
||||||
|
@ -178,6 +200,14 @@ public class Debugger {
|
||||||
list.add(debugInfo);
|
list.add(debugInfo);
|
||||||
}
|
}
|
||||||
scriptMap.put(debugInfo, name);
|
scriptMap.put(debugInfo, name);
|
||||||
|
for (Breakpoint breakpoint : breakpoints) {
|
||||||
|
updateInternalBreakpoints(breakpoint);
|
||||||
|
updateBreakpointStatus(breakpoint, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAttached() {
|
||||||
|
return javaScriptDebugger.isAttached();
|
||||||
}
|
}
|
||||||
|
|
||||||
private JavaScriptDebuggerListener javaScriptListener = new JavaScriptDebuggerListener() {
|
private JavaScriptDebuggerListener javaScriptListener = new JavaScriptDebuggerListener() {
|
||||||
|
@ -203,5 +233,35 @@ public class Debugger {
|
||||||
public void scriptAdded(String name) {
|
public void scriptAdded(String name) {
|
||||||
addScript(name);
|
addScript(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void attached() {
|
||||||
|
for (Breakpoint breakpoint : breakpoints) {
|
||||||
|
updateInternalBreakpoints(breakpoint);
|
||||||
|
updateBreakpointStatus(breakpoint, false);
|
||||||
|
}
|
||||||
|
for (DebuggerListener listener : listeners) {
|
||||||
|
listener.attached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void detached() {
|
||||||
|
for (Breakpoint breakpoint : breakpoints) {
|
||||||
|
updateBreakpointStatus(breakpoint, true);
|
||||||
|
}
|
||||||
|
for (DebuggerListener listener : listeners) {
|
||||||
|
listener.detached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void breakpointChanged(JavaScriptBreakpoint jsBreakpoint) {
|
||||||
|
Breakpoint breakpoint = breakpointMap.get(jsBreakpoint);
|
||||||
|
if (breakpoint != null) {
|
||||||
|
updateInternalBreakpoints(breakpoint);
|
||||||
|
updateBreakpointStatus(breakpoint, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,4 +23,10 @@ public interface DebuggerListener {
|
||||||
void resumed();
|
void resumed();
|
||||||
|
|
||||||
void paused();
|
void paused();
|
||||||
|
|
||||||
|
void breakpointStatusChanged(Breakpoint breakpoint);
|
||||||
|
|
||||||
|
void attached();
|
||||||
|
|
||||||
|
void detached();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,5 +22,7 @@ package org.teavm.debugging;
|
||||||
public interface JavaScriptBreakpoint {
|
public interface JavaScriptBreakpoint {
|
||||||
JavaScriptLocation getLocation();
|
JavaScriptLocation getLocation();
|
||||||
|
|
||||||
|
boolean isValid();
|
||||||
|
|
||||||
void destroy();
|
void destroy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,8 @@ public interface JavaScriptDebugger {
|
||||||
|
|
||||||
boolean isSuspended();
|
boolean isSuspended();
|
||||||
|
|
||||||
|
boolean isAttached();
|
||||||
|
|
||||||
JavaScriptCallFrame[] getCallStack();
|
JavaScriptCallFrame[] getCallStack();
|
||||||
|
|
||||||
JavaScriptBreakpoint getCurrentBreakpoint();
|
JavaScriptBreakpoint getCurrentBreakpoint();
|
||||||
|
|
|
@ -24,5 +24,11 @@ public interface JavaScriptDebuggerListener {
|
||||||
|
|
||||||
void resumed();
|
void resumed();
|
||||||
|
|
||||||
|
void attached();
|
||||||
|
|
||||||
|
void detached();
|
||||||
|
|
||||||
|
void breakpointChanged(JavaScriptBreakpoint breakpoint);
|
||||||
|
|
||||||
void scriptAdded(String name);
|
void scriptAdded(String name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1498,6 +1498,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
||||||
writer.append("(");
|
writer.append("(");
|
||||||
expr.getExpr().acceptVisitor(this);
|
expr.getExpr().acceptVisitor(this);
|
||||||
writer.append(" instanceof ").appendClass(clsName).append(")");
|
writer.append(" instanceof ").appendClass(clsName).append(")");
|
||||||
|
if (expr.getLocation() != null) {
|
||||||
|
popLocation();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user