This commit is contained in:
Alexey Andreev 2014-07-29 17:13:29 +04:00
parent ba9f6ef718
commit 81fff7a4a6
20 changed files with 87 additions and 25 deletions

View File

@ -20,7 +20,11 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.websocket.*;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.teavm.chromerpd.data.CallFrameDTO;
@ -34,7 +38,7 @@ import org.teavm.debugging.*;
*
* @author Alexey Andreev
*/
@ClientEndpoint
@ServerEndpoint("/")
public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
private List<JavaScriptDebuggerListener> listeners = new ArrayList<>();
private Session session;
@ -46,19 +50,25 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger {
private Map<Integer, Deferred> deferredResponses = new HashMap<>();
private int messageIdGenerator;
boolean closed;
private ChromeRDPContainer container;
@OnOpen
public void open(Session session) {
this.session = session;
Object container = session.getUserProperties().get("container");
Object container = session.getUserProperties().get("rdp.container");
if (container instanceof ChromeRDPContainer) {
((ChromeRDPContainer)container).setDebugger(this);
this.container = (ChromeRDPContainer)container;
this.container.setDebugger(this);
}
}
@OnClose
public void close() {
closed = true;
if (this.container != null) {
this.container.setDebugger(null);
this.container = null;
}
}
@OnMessage

View File

@ -63,7 +63,7 @@ public class ChromeRDPServer {
}
public void start() {
Server server = new Server();
final Server server = new Server();
ServerConnector connector = new ServerConnector(server);
connector.setPort(port);
server.addConnector(connector);
@ -78,6 +78,7 @@ public class ChromeRDPServer {
wscontainer.addEndpoint(new RPDEndpointConfig());
server.start();
server.dump(output);
server.join();
} catch (Exception e) {
throw new RuntimeException(e);
}
@ -140,11 +141,15 @@ public class ChromeRDPServer {
}
void setDebugger(JavaScriptDebugger debugger) {
if (!this.debugger.compareAndSet(null, debugger)) {
throw new IllegalStateException("Can't handle more than one connection");
}
for (ChromeRDPServerListener listener : listeners) {
listener.connected(this);
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);
}
}
}

View File

@ -15,10 +15,13 @@
*/
package org.teavm.chromerpd.data;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class CallFrameDTO {
private String callFrameId;
private LocationDTO location;

View File

@ -15,10 +15,13 @@
*/
package org.teavm.chromerpd.data;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class LocationDTO {
private int columnNumber;
private int lineNumber;

View File

@ -16,11 +16,13 @@
package org.teavm.chromerpd.data;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Message {
private Integer id;
private String method;

View File

@ -16,11 +16,13 @@
package org.teavm.chromerpd.data;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Response {
private int id;
private JsonNode result;

View File

@ -15,12 +15,14 @@
*/
package org.teavm.chromerpd.messages;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.teavm.chromerpd.data.LocationDTO;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class ContinueToLocationCommand {
private LocationDTO location;

View File

@ -15,10 +15,13 @@
*/
package org.teavm.chromerpd.messages;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class RemoveBreakpointCommand {
private String breakpointId;

View File

@ -15,10 +15,13 @@
*/
package org.teavm.chromerpd.messages;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class ScriptParsedNotification {
private String scriptId;
private String url;

View File

@ -15,12 +15,14 @@
*/
package org.teavm.chromerpd.messages;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.teavm.chromerpd.data.LocationDTO;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class SetBreakpointCommand {
private LocationDTO location;

View File

@ -15,12 +15,14 @@
*/
package org.teavm.chromerpd.messages;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.teavm.chromerpd.data.LocationDTO;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class SetBreakpointResponse {
private String breakpointId;
private LocationDTO actualLocation;

View File

@ -16,12 +16,14 @@
package org.teavm.chromerpd.messages;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.teavm.chromerpd.data.CallFrameDTO;
/**
*
* @author Alexey Andreev
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class SuspendedNotification {
private CallFrameDTO[] callFrames;
private String reason;

View File

@ -4,6 +4,7 @@ chrome.browserAction.onClicked.addListener(function(tab) {
new DebuggerAgent(tab).attach();
});
function DebuggerAgent(tab) {
this.pendingMessages = [];
this.connection = null;
this.tab = null;
this.debuggee = { tabId : tab.id };
@ -14,12 +15,12 @@ DebuggerAgent.prototype.attach = function() {
chrome.debugger.attach(this.debuggee, "1.0", (function(callback) {
this.attachedToDebugger = true;
chrome.debugger.sendCommand(this.debuggee, "Debugger.enable", {}, callback);
}).bind(this, connectToServer.bind(this)));
}).bind(this, this.connectToServer.bind(this)));
};
DebuggerAgent.prototype.connectToServer = function() {
this.connection = new WebSocket("ws://localhost:2357/");
this.connection.onmessage = function(event) {
receiveMessage(this.debuggee, this.connection, JSON.parse(event.data));
this.receiveMessage(JSON.parse(event.data));
}.bind(this);
this.connection.onclose = function(event) {
if (this.connection != null) {
@ -27,6 +28,12 @@ DebuggerAgent.prototype.connectToServer = function() {
this.disconnect();
}
}.bind(this);
this.connection.onopen = function() {
for (var i = 0; i < this.pendingMessages.length; ++i) {
this.connection.send(JSON.stringify(this.pendingMessages[i]));
}
this.pendingMessages = null;
}.bind(this);
};
DebuggerAgent.prototype.receiveMessage = function(message) {
chrome.debugger.sendCommand(this.debuggee, message.method, message.params, function(response) {
@ -58,7 +65,11 @@ chrome.debugger.onEvent.addListener(function(source, method, params) {
return;
}
var message = { method : method, params : params };
this.connection.send(JSON.stringify(message));
if (agent.pendingMessages) {
agent.pendingMessages.push(message);
} else if (agent.connection) {
agent.connection.send(JSON.stringify(message));
}
});
chrome.debugger.onDetach.addListener(function(source) {
var agent = debuggerAgentMap[source.tabId];

View File

@ -15,5 +15,5 @@
"background": {
"scripts": ["main.js"],
"persistent": false
},
}
}

View File

@ -45,7 +45,7 @@ class DebugInformationReader {
}
private int processSign(int number) {
boolean negative = (number & 1) == 1;
boolean negative = (number & 1) != 0;
number >>>= 1;
return !negative ? number : -number;
}
@ -57,12 +57,12 @@ class DebugInformationReader {
last += lines[i];
lines[i] = last;
}
int[] columns = new int[readUnsignedNumber()];
int[] columns = new int[lines.length];
resetRelativeNumber();
for (int i = 0; i < columns.length; ++i) {
columns[i] = readRelativeNumber();
}
int[] values = new int[readUnsignedNumber()];
int[] values = new int[lines.length];
resetRelativeNumber();
for (int i = 0; i < values.length; ++i) {
values[i] = readRelativeNumber();
@ -88,7 +88,7 @@ class DebugInformationReader {
}
n = processSign(n >>> 1);
while (count-- > 0) {
array[i] = n;
array[i++] = n;
}
}
return array;
@ -100,13 +100,15 @@ class DebugInformationReader {
private int readUnsignedNumber() throws IOException {
int number = 0;
int shift = 0;
while (true) {
int r = input.read();
if (r < 0) {
throw new EOFException();
}
byte b = (byte)r;
number = (number << 7) | (b & 0x7F);
number |= (b & 0x7F) << shift;
shift += 7;
if ((b & 0x80) == 0) {
break;
}

View File

@ -49,7 +49,6 @@ class DebugInformationWriter {
}
private void writeMapping(DebugInformation.Mapping mapping) throws IOException {
writeUnsignedNumber(mapping.lines.length);
int[] lines = mapping.lines.clone();
int last = 0;
for (int i = 0; i < lines.length; ++i) {

View File

@ -165,6 +165,9 @@ public class Debugger {
return;
}
DebugInformation debugInfo = debugInformationProvider.getDebugInformation(name);
if (debugInfo == null) {
return;
}
debugInformationMap.put(name, debugInfo);
for (String sourceFile : debugInfo.getCoveredSourceFiles()) {
List<DebugInformation> list = debugInformationFileMap.get(sourceFile);

View File

@ -36,4 +36,9 @@ public class SourceLocation {
public int getLine() {
return line;
}
@Override
public String toString() {
return fileName + ":" + line;
}
}

View File

@ -33,7 +33,7 @@ public class URLDebugInformationProvider implements DebugInformationProvider {
@Override
public DebugInformation getDebugInformation(String script) {
try {
URL url = new URL(baseURL + script);
URL url = new URL(baseURL + script + ".teavmdbg");
try (InputStream input = url.openStream()) {
return DebugInformation.read(input);
}

View File

@ -495,13 +495,16 @@ class StatementGenerator implements InstructionVisitor {
@Override
public void visit(PutFieldInstruction insn) {
Expr right = Expr.var(insn.getValue().getIndex());
Expr left;
if (insn.getInstance() != null) {
assign(Expr.qualify(Expr.var(insn.getInstance().getIndex()), insn.getField()), insn.getValue().getIndex());
left = Expr.qualify(Expr.var(insn.getInstance().getIndex()), insn.getField());
} else {
Expr fieldExpr = Expr.qualify(Expr.staticClass(ValueType.object(insn.getField().getClassName())),
insn.getField());
assign(fieldExpr, insn.getValue().getIndex());
left = Expr.qualify(Expr.staticClass(ValueType.object(insn.getField().getClassName())), insn.getField());
}
AssignmentStatement stmt = Statement.assign(left, right);
stmt.setLocation(currentLocation);
statements.add(stmt);
}
@Override