diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPDebuggerEndpoint.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPDebuggerEndpoint.java index 665432607..f5c56263f 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPDebuggerEndpoint.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPDebuggerEndpoint.java @@ -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 listeners = new ArrayList<>(); private Session session; @@ -46,19 +50,25 @@ public class ChromeRDPDebuggerEndpoint implements JavaScriptDebugger { private Map 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 diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPServer.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPServer.java index 00b8ff649..aaeb2d3fe 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPServer.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPServer.java @@ -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); } } } diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/CallFrameDTO.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/CallFrameDTO.java index a0fc1bb15..4c57ef0f8 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/CallFrameDTO.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/CallFrameDTO.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/LocationDTO.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/LocationDTO.java index 8136468a4..13a17bf83 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/LocationDTO.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/LocationDTO.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Message.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Message.java index 22cd25a44..0a4fec1c1 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Message.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Message.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Response.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Response.java index da7fa6046..9699f9b30 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Response.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Response.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ContinueToLocationCommand.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ContinueToLocationCommand.java index ce70864dd..52c1241f1 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ContinueToLocationCommand.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ContinueToLocationCommand.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/RemoveBreakpointCommand.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/RemoveBreakpointCommand.java index 14f7195fe..ba109fc2d 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/RemoveBreakpointCommand.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/RemoveBreakpointCommand.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ScriptParsedNotification.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ScriptParsedNotification.java index 9fab6dcbc..808447a1e 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ScriptParsedNotification.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ScriptParsedNotification.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SetBreakpointCommand.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SetBreakpointCommand.java index 18e85e470..1dd971032 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SetBreakpointCommand.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SetBreakpointCommand.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SetBreakpointResponse.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SetBreakpointResponse.java index 0850f5370..ea355bd9a 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SetBreakpointResponse.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SetBreakpointResponse.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SuspendedNotification.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SuspendedNotification.java index a1e990d6e..8f86739b6 100644 --- a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SuspendedNotification.java +++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SuspendedNotification.java @@ -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; diff --git a/teavm-chrome-rdp/src/main/js/chrome/main.js b/teavm-chrome-rdp/src/main/js/chrome/main.js index 56f485086..684e31042 100644 --- a/teavm-chrome-rdp/src/main/js/chrome/main.js +++ b/teavm-chrome-rdp/src/main/js/chrome/main.js @@ -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]; diff --git a/teavm-chrome-rdp/src/main/js/chrome/manifest.json b/teavm-chrome-rdp/src/main/js/chrome/manifest.json index 460c9c669..5b15ec3b1 100644 --- a/teavm-chrome-rdp/src/main/js/chrome/manifest.json +++ b/teavm-chrome-rdp/src/main/js/chrome/manifest.json @@ -15,5 +15,5 @@ "background": { "scripts": ["main.js"], "persistent": false - }, + } } \ No newline at end of file diff --git a/teavm-core/src/main/java/org/teavm/debugging/DebugInformationReader.java b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationReader.java index c22e36851..868c0d09b 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/DebugInformationReader.java +++ b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationReader.java @@ -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; } diff --git a/teavm-core/src/main/java/org/teavm/debugging/DebugInformationWriter.java b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationWriter.java index aaab23d4e..0029978d9 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/DebugInformationWriter.java +++ b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationWriter.java @@ -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) { diff --git a/teavm-core/src/main/java/org/teavm/debugging/Debugger.java b/teavm-core/src/main/java/org/teavm/debugging/Debugger.java index 8521b1881..2c8994886 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/Debugger.java +++ b/teavm-core/src/main/java/org/teavm/debugging/Debugger.java @@ -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 list = debugInformationFileMap.get(sourceFile); diff --git a/teavm-core/src/main/java/org/teavm/debugging/SourceLocation.java b/teavm-core/src/main/java/org/teavm/debugging/SourceLocation.java index 28625420f..208dee42a 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/SourceLocation.java +++ b/teavm-core/src/main/java/org/teavm/debugging/SourceLocation.java @@ -36,4 +36,9 @@ public class SourceLocation { public int getLine() { return line; } + + @Override + public String toString() { + return fileName + ":" + line; + } } diff --git a/teavm-core/src/main/java/org/teavm/debugging/URLDebugInformationProvider.java b/teavm-core/src/main/java/org/teavm/debugging/URLDebugInformationProvider.java index 8159a9cc4..eb50bd819 100644 --- a/teavm-core/src/main/java/org/teavm/debugging/URLDebugInformationProvider.java +++ b/teavm-core/src/main/java/org/teavm/debugging/URLDebugInformationProvider.java @@ -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); } diff --git a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java index fd1d0e5d3..aaf3e8b2f 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java @@ -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