diff --git a/pom.xml b/pom.xml
index 68e4aa6a2..95f370fc7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,8 +65,10 @@
UTF-8
- 0.7.5
https://oss.sonatype.org/content/repositories/snapshots/
+ 0.7.5
+ 9.2.1.v20140609
+ 1.7.7
@@ -79,6 +81,7 @@
teavm-samples
teavm-platform
teavm-cli
+ teavm-chrome-rdp
@@ -134,6 +137,26 @@
maven-core
3.0
+
+ javax.websocket
+ javax.websocket-api
+ 1.0
+
+
+ org.eclipse.jetty
+ jetty-server
+ ${jetty.version}
+
+
+ org.eclipse.jetty.websocket
+ javax-websocket-server-impl
+ ${jetty.version}
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
diff --git a/teavm-chrome-rdp/.gitignore b/teavm-chrome-rdp/.gitignore
new file mode 100644
index 000000000..c708c363d
--- /dev/null
+++ b/teavm-chrome-rdp/.gitignore
@@ -0,0 +1,4 @@
+/target
+/.settings
+/.classpath
+/.project
diff --git a/teavm-chrome-rdp/pom.xml b/teavm-chrome-rdp/pom.xml
new file mode 100644
index 000000000..580e21dc2
--- /dev/null
+++ b/teavm-chrome-rdp/pom.xml
@@ -0,0 +1,88 @@
+
+
+ 4.0.0
+
+
+ org.teavm
+ teavm
+ 0.2-SNAPSHOT
+
+ teavm-chrome-rdp
+
+ TeaVM debugging backend for Google Chrome RDP
+ TeaVM debugging backend for Google Chrome RDP
+
+
+
+ org.eclipse.jetty
+ jetty-server
+
+
+ org.eclipse.jetty.websocket
+ javax-websocket-server-impl
+
+
+ org.teavm
+ teavm-core
+ ${project.version}
+
+
+ org.slf4j
+ slf4j-api
+
+
+ javax.websocket
+ javax.websocket-api
+
+
+ org.eclipse.jetty
+ jetty-server
+
+
+ org.eclipse.jetty.websocket
+ javax-websocket-server-impl
+
+
+ org.slf4j
+ slf4j-api
+
+
+ org.codehaus.jackson
+ jackson-core-asl
+ 1.9.13
+
+
+ org.codehaus.jackson
+ jackson-mapper-asl
+ 1.9.13
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+
+
+
+
\ No newline at end of file
diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPDebugger.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPDebugger.java
new file mode 100644
index 000000000..4d9cb2590
--- /dev/null
+++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/ChromeRDPDebugger.java
@@ -0,0 +1,202 @@
+/*
+ * 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;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+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.JsonProcessingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.teavm.chromerpd.data.CallFrameDTO;
+import org.teavm.chromerpd.data.LocationDTO;
+import org.teavm.chromerpd.data.Message;
+import org.teavm.chromerpd.messages.ContinueToLocationCommand;
+import org.teavm.chromerpd.messages.ScriptParsedNotification;
+import org.teavm.chromerpd.messages.SuspendedNotification;
+import org.teavm.debugging.*;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+@ServerEndpoint("/")
+public class ChromeRDPDebugger implements JavaScriptDebugger {
+ private List listeners = new ArrayList<>();
+ private Session session;
+ private RDPCallFrame[] callStack = new RDPCallFrame[0];
+ private Map scripts = new HashMap<>();
+ private Map scriptIds = new HashMap<>();
+ private boolean suspended;
+ private ObjectMapper mapper = new ObjectMapper();
+
+ @OnOpen
+ public void open(Session session) {
+ this.session = session;
+ }
+
+ @OnMessage
+ public void receive(String messageText) throws IOException {
+ Message message = mapper.reader(Message.class).readValue(messageText);
+ switch (message.getMethod()) {
+ case "Debugger.paused":
+ firePaused(parseJson(SuspendedNotification.class, message.getParams()));
+ break;
+ case "Debugger.resumed":
+ fireResumed();
+ break;
+ case "Debugger.scriptParsed":
+ scriptParsed(parseJson(ScriptParsedNotification.class, message.getParams()));
+ break;
+ }
+ }
+
+ private T parseJson(Class type, JsonNode node) throws IOException {
+ return mapper.reader(type).readValue(node);
+ }
+
+ private void firePaused(SuspendedNotification params) {
+ suspended = true;
+ CallFrameDTO[] callFrameDTOs = params.getCallFrames();
+ RDPCallFrame[] callFrames = new RDPCallFrame[callFrameDTOs.length];
+ for (int i = 0; i < callFrames.length; ++i) {
+ callFrames[i] = map(callFrameDTOs[i]);
+ }
+ for (JavaScriptDebuggerListener listener : listeners) {
+ listener.paused();
+ }
+ }
+
+ RDPCallFrame map(CallFrameDTO dto) {
+ return new RDPCallFrame(dto.getCallFrameId(), map(dto.getLocation()));
+ }
+
+ JavaScriptLocation map(LocationDTO dto) {
+ return new JavaScriptLocation(scripts.get(dto.getScriptId()), dto.getLineNumber(), dto.getColumnNumber());
+ }
+
+ private void fireResumed() {
+ suspended = false;
+ for (JavaScriptDebuggerListener listener : listeners) {
+ listener.resumed();
+ }
+ }
+
+ private void scriptParsed(ScriptParsedNotification params) {
+ if (scripts.containsKey(params.getScriptId())) {
+ return;
+ }
+ scripts.put(params.getScriptId(), params.getUrl());
+ scriptIds.put(params.getUrl(), params.getScriptId());
+ for (JavaScriptDebuggerListener listener : listeners) {
+ 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) {
+ try {
+ String messageText = mapper.writer().writeValueAsString(message);
+ session.getAsyncRemote().sendText(messageText);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void suspend() {
+ Message message = new Message();
+ message.setMethod("Debugger.pause");
+ sendMessage(message);
+ }
+
+ @Override
+ public void resume() {
+ Message message = new Message();
+ message.setMethod("Debugger.resume");
+ sendMessage(message);
+ }
+
+ @Override
+ public void stepInto() {
+ Message message = new Message();
+ message.setMethod("Debugger.stepInto");
+ sendMessage(message);
+ }
+
+ @Override
+ public void stepOut() {
+ Message message = new Message();
+ message.setMethod("Debugger.stepOut");
+ sendMessage(message);
+ }
+
+ @Override
+ public void stepOver() {
+ Message message = new Message();
+ message.setMethod("Debugger.stepOver");
+ sendMessage(message);
+ }
+
+ @Override
+ public void continueToLocation(JavaScriptLocation location) {
+ Message message = new Message();
+ message.setMethod("Debugger.continueToLocation");
+ ContinueToLocationCommand params = new ContinueToLocationCommand();
+ LocationDTO locationDTO = new LocationDTO();
+ locationDTO.setScriptId(scriptIds.get(location.getScript()));
+ locationDTO.setLineNumber(location.getLine());
+ locationDTO.setColumnNumber(location.getColumn());
+ params.setLocation(locationDTO);
+ message.setParams(mapper.valueToTree(params));
+ sendMessage(message);
+ }
+
+ @Override
+ public boolean isSuspended() {
+ return suspended;
+ }
+
+ @Override
+ public JavaScriptCallFrame[] getCallStack() {
+ return callStack;
+ }
+
+ @Override
+ public JavaScriptBreakpoint getCurrentBreakpoint() {
+ return null;
+ }
+
+ @Override
+ public JavaScriptBreakpoint createBreakpoint(JavaScriptLocation location) {
+ return null;
+ }
+}
diff --git a/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/RDPCallFrame.java b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/RDPCallFrame.java
new file mode 100644
index 000000000..32cf1f7a1
--- /dev/null
+++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/RDPCallFrame.java
@@ -0,0 +1,42 @@
+/*
+ * 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;
+
+import org.teavm.debugging.JavaScriptCallFrame;
+import org.teavm.debugging.JavaScriptLocation;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class RDPCallFrame implements JavaScriptCallFrame {
+ private String chromeId;
+ private JavaScriptLocation location;
+
+ public RDPCallFrame(String chromeId, JavaScriptLocation location) {
+ this.chromeId = chromeId;
+ this.location = location;
+ }
+
+ public String getChromeId() {
+ return chromeId;
+ }
+
+ @Override
+ public JavaScriptLocation getLocation() {
+ return location;
+ }
+}
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
new file mode 100644
index 000000000..a0fc1bb15
--- /dev/null
+++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/CallFrameDTO.java
@@ -0,0 +1,41 @@
+/*
+ * 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.data;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class CallFrameDTO {
+ private String callFrameId;
+ private LocationDTO location;
+
+ public String getCallFrameId() {
+ return callFrameId;
+ }
+
+ public void setCallFrameId(String callFrameId) {
+ this.callFrameId = callFrameId;
+ }
+
+ public LocationDTO getLocation() {
+ return location;
+ }
+
+ public void setLocation(LocationDTO location) {
+ this.location = 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
new file mode 100644
index 000000000..8136468a4
--- /dev/null
+++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/LocationDTO.java
@@ -0,0 +1,50 @@
+/*
+ * 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.data;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class LocationDTO {
+ private int columnNumber;
+ private int lineNumber;
+ private String scriptId;
+
+ public int getColumnNumber() {
+ return columnNumber;
+ }
+
+ public void setColumnNumber(int columnNumber) {
+ this.columnNumber = columnNumber;
+ }
+
+ public int getLineNumber() {
+ return lineNumber;
+ }
+
+ public void setLineNumber(int lineNumber) {
+ this.lineNumber = lineNumber;
+ }
+
+ public String getScriptId() {
+ return scriptId;
+ }
+
+ public void setScriptId(String scriptId) {
+ this.scriptId = scriptId;
+ }
+}
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
new file mode 100644
index 000000000..ff8675522
--- /dev/null
+++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/data/Message.java
@@ -0,0 +1,43 @@
+/*
+ * 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.data;
+
+import org.codehaus.jackson.JsonNode;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class Message {
+ private String method;
+ private JsonNode params;
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ public JsonNode getParams() {
+ return params;
+ }
+
+ public void setParams(JsonNode params) {
+ this.params = params;
+ }
+}
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
new file mode 100644
index 000000000..ce70864dd
--- /dev/null
+++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ContinueToLocationCommand.java
@@ -0,0 +1,34 @@
+/*
+ * 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.messages;
+
+import org.teavm.chromerpd.data.LocationDTO;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class ContinueToLocationCommand {
+ private LocationDTO location;
+
+ public LocationDTO getLocation() {
+ return location;
+ }
+
+ public void setLocation(LocationDTO location) {
+ this.location = location;
+ }
+}
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
new file mode 100644
index 000000000..9fab6dcbc
--- /dev/null
+++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/ScriptParsedNotification.java
@@ -0,0 +1,41 @@
+/*
+ * 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.messages;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class ScriptParsedNotification {
+ private String scriptId;
+ private String url;
+
+ public String getScriptId() {
+ return scriptId;
+ }
+
+ public void setScriptId(String scriptId) {
+ this.scriptId = scriptId;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+}
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
new file mode 100644
index 000000000..a1e990d6e
--- /dev/null
+++ b/teavm-chrome-rdp/src/main/java/org/teavm/chromerpd/messages/SuspendedNotification.java
@@ -0,0 +1,53 @@
+/*
+ * 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.messages;
+
+import org.codehaus.jackson.JsonNode;
+import org.teavm.chromerpd.data.CallFrameDTO;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class SuspendedNotification {
+ private CallFrameDTO[] callFrames;
+ private String reason;
+ private JsonNode data;
+
+ public CallFrameDTO[] getCallFrames() {
+ return callFrames;
+ }
+
+ public void setCallFrames(CallFrameDTO[] callFrames) {
+ this.callFrames = callFrames;
+ }
+
+ public String getReason() {
+ return reason;
+ }
+
+ public void setReason(String reason) {
+ this.reason = reason;
+ }
+
+ public JsonNode getData() {
+ return data;
+ }
+
+ public void setData(JsonNode data) {
+ this.data = data;
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/debugging/DebugInformation.java b/teavm-core/src/main/java/org/teavm/debugging/DebugInformation.java
index c9415ac21..9cdf877f5 100644
--- a/teavm-core/src/main/java/org/teavm/debugging/DebugInformation.java
+++ b/teavm-core/src/main/java/org/teavm/debugging/DebugInformation.java
@@ -41,6 +41,10 @@ public class DebugInformation {
Mapping methodMapping;
Mapping lineMapping;
+ public String[] getCoveredSourceFiles() {
+ return fileNames.clone();
+ }
+
public Collection getGeneratedLocations(String fileName, int line) {
Integer fileIndex = fileNameMap.get(fileName);
if (fileIndex == null) {
@@ -90,6 +94,10 @@ public class DebugInformation {
return new MethodReference(className, MethodDescriptor.parse(method));
}
+ public MethodReference getMethodAt(int line, int column) {
+ return getMethodAt(new GeneratedLocation(line, column));
+ }
+
private T componentByKey(Mapping mapping, T[] values, GeneratedLocation location) {
int keyIndex = indexByKey(mapping, location);
int valueIndex = keyIndex >= 0 ? mapping.values[keyIndex] : -1;
@@ -106,7 +114,7 @@ public class DebugInformation {
writer.write(this);
}
- public DebugInformation read(InputStream input) throws IOException {
+ public static DebugInformation read(InputStream input) throws IOException {
DebugInformationReader reader = new DebugInformationReader(input);
return reader.read();
}
diff --git a/teavm-core/src/main/java/org/teavm/debugging/DebugInformationProvider.java b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationProvider.java
new file mode 100644
index 000000000..9c8ccafb1
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/debugging/DebugInformationProvider.java
@@ -0,0 +1,24 @@
+/*
+ * 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.debugging;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public interface DebugInformationProvider {
+ DebugInformation getDebugInformation(String script);
+}
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 e77a77920..77ac0f960 100644
--- a/teavm-core/src/main/java/org/teavm/debugging/Debugger.java
+++ b/teavm-core/src/main/java/org/teavm/debugging/Debugger.java
@@ -27,14 +27,17 @@ import org.teavm.model.MethodReference;
public class Debugger {
private List listeners = new ArrayList<>();
private JavaScriptDebugger javaScriptDebugger;
- private DebugInformation debugInformation;
+ private DebugInformationProvider debugInformationProvider;
private List temporaryJsBreakpoints = new ArrayList<>();
+ private Map debugInformationMap = new HashMap<>();
+ private Map> debugInformationFileMap = new HashMap<>();
+ private Map scriptMap = new HashMap<>();
Map breakpointMap = new HashMap<>();
private CallFrame[] callStack;
- public Debugger(JavaScriptDebugger javaScriptDebugger, DebugInformation debugInformation) {
+ public Debugger(JavaScriptDebugger javaScriptDebugger, DebugInformationProvider debugInformationProvider) {
this.javaScriptDebugger = javaScriptDebugger;
- this.debugInformation = debugInformation;
+ this.debugInformationProvider = debugInformationProvider;
javaScriptDebugger.addListener(javaScriptListener);
}
@@ -65,7 +68,6 @@ public class Debugger {
if (!javaScriptDebugger.isSuspended()) {
return;
}
- // TODO: lookup all locations that are "out of" the current location and create temporary breakpoints
javaScriptDebugger.stepOut();
}
@@ -74,18 +76,26 @@ public class Debugger {
return;
}
javaScriptDebugger.stepOver();
- // TODO: lookup all locations that are "after" the current location and create temporary breakpoints
+ }
+
+ private List debugInformationBySource(String sourceFile) {
+ List list = debugInformationFileMap.get(sourceFile);
+ return list != null ? list : Collections.emptyList();
}
public void continueToLocation(String fileName, int line) {
if (!javaScriptDebugger.isSuspended()) {
return;
}
- Collection locations = debugInformation.getGeneratedLocations(fileName, line);
- for (GeneratedLocation location : locations) {
- JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(location);
- if (jsBreakpoint != null) {
- temporaryJsBreakpoints.add(jsBreakpoint);
+ for (DebugInformation debugInformation : debugInformationBySource(fileName)) {
+ Collection locations = debugInformation.getGeneratedLocations(fileName, line);
+ for (GeneratedLocation location : locations) {
+ JavaScriptLocation jsLocation = new JavaScriptLocation(scriptMap.get(debugInformation),
+ location.getLine(), location.getColumn());
+ JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(jsLocation);
+ if (jsBreakpoint != null) {
+ temporaryJsBreakpoints.add(jsBreakpoint);
+ }
}
}
javaScriptDebugger.resume();
@@ -96,12 +106,16 @@ public class Debugger {
}
public Breakpoint createBreakpoint(String fileName, int line) {
- Collection locations = debugInformation.getGeneratedLocations(fileName, line);
List jsBreakpoints = new ArrayList<>();
- for (GeneratedLocation location : locations) {
- JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(location);
- if (jsBreakpoint != null) {
- jsBreakpoints.add(jsBreakpoint);
+ for (DebugInformation debugInformation : debugInformationBySource(fileName)) {
+ Collection locations = debugInformation.getGeneratedLocations(fileName, line);
+ for (GeneratedLocation location : locations) {
+ JavaScriptLocation jsLocation = new JavaScriptLocation(scriptMap.get(debugInformation),
+ location.getLine(), location.getColumn());
+ JavaScriptBreakpoint jsBreakpoint = javaScriptDebugger.createBreakpoint(jsLocation);
+ if (jsBreakpoint != null) {
+ jsBreakpoints.add(jsBreakpoint);
+ }
}
}
return !jsBreakpoints.isEmpty() ? new Breakpoint(this, jsBreakpoints, fileName, line) : null;
@@ -117,9 +131,17 @@ public class Debugger {
List frames = new ArrayList<>();
boolean wasEmpty = false;
for (JavaScriptCallFrame jsFrame : javaScriptDebugger.getCallStack()) {
- SourceLocation loc = debugInformation.getSourceLocation(jsFrame.getLocation());
+ DebugInformation debugInformation = debugInformationMap.get(jsFrame.getLocation().getScript());
+ SourceLocation loc;
+ if (debugInformation != null) {
+ loc = debugInformation.getSourceLocation(jsFrame.getLocation().getLine(),
+ jsFrame.getLocation().getColumn());
+ } else {
+ loc = null;
+ }
boolean empty = loc == null || (loc.getFileName() == null && loc.getLine() < 0);
- MethodReference method = !empty ? debugInformation.getMethodAt(jsFrame.getLocation()) : null;
+ MethodReference method = !empty ? debugInformation.getMethodAt(jsFrame.getLocation().getLine(),
+ jsFrame.getLocation().getColumn()) : null;
if (!empty || !wasEmpty) {
frames.add(new CallFrame(loc, method));
}
@@ -130,6 +152,23 @@ public class Debugger {
return callStack.clone();
}
+ private void addScript(String name) {
+ if (debugInformationMap.containsKey(name)) {
+ return;
+ }
+ DebugInformation debugInfo = debugInformationProvider.getDebugInformation(name);
+ debugInformationMap.put(name, debugInfo);
+ for (String sourceFile : debugInfo.getCoveredSourceFiles()) {
+ List list = debugInformationFileMap.get(sourceFile);
+ if (list == null) {
+ list = new ArrayList<>();
+ debugInformationFileMap.put(sourceFile, list);
+ }
+ list.add(debugInfo);
+ }
+ scriptMap.put(debugInfo, name);
+ }
+
private JavaScriptDebuggerListener javaScriptListener = new JavaScriptDebuggerListener() {
@Override
public void resumed() {
@@ -148,5 +187,10 @@ public class Debugger {
listener.paused();
}
}
+
+ @Override
+ public void scriptAdded(String name) {
+ addScript(name);
+ }
};
}
diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptBreakpoint.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptBreakpoint.java
index 5923c7426..f6934836f 100644
--- a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptBreakpoint.java
+++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptBreakpoint.java
@@ -28,7 +28,7 @@ public interface JavaScriptBreakpoint {
String getFileName();
- GeneratedLocation getLocation();
+ JavaScriptLocation getLocation();
void destroy();
}
diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptCallFrame.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptCallFrame.java
index 21bfcbbed..a0a6d4c4a 100644
--- a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptCallFrame.java
+++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptCallFrame.java
@@ -20,5 +20,5 @@ package org.teavm.debugging;
* @author Alexey Andreev
*/
public interface JavaScriptCallFrame {
- GeneratedLocation getLocation();
+ JavaScriptLocation getLocation();
}
diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebugger.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebugger.java
index b8114193a..a6cfcfcbc 100644
--- a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebugger.java
+++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebugger.java
@@ -34,7 +34,7 @@ public interface JavaScriptDebugger {
void stepOver();
- void continueToLocation(GeneratedLocation location);
+ void continueToLocation(JavaScriptLocation location);
boolean isSuspended();
@@ -42,5 +42,5 @@ public interface JavaScriptDebugger {
JavaScriptBreakpoint getCurrentBreakpoint();
- JavaScriptBreakpoint createBreakpoint(GeneratedLocation location);
+ JavaScriptBreakpoint createBreakpoint(JavaScriptLocation location);
}
diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebuggerListener.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebuggerListener.java
index a8b076bba..a7e99a37e 100644
--- a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebuggerListener.java
+++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptDebuggerListener.java
@@ -23,4 +23,6 @@ public interface JavaScriptDebuggerListener {
void paused();
void resumed();
+
+ void scriptAdded(String name);
}
diff --git a/teavm-core/src/main/java/org/teavm/debugging/JavaScriptLocation.java b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptLocation.java
new file mode 100644
index 000000000..2cee84c2d
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/debugging/JavaScriptLocation.java
@@ -0,0 +1,44 @@
+/*
+ * 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.debugging;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class JavaScriptLocation {
+ private String script;
+ private int line;
+ private int column;
+
+ public JavaScriptLocation(String script, int line, int column) {
+ this.script = script;
+ this.line = line;
+ this.column = column;
+ }
+
+ public String getScript() {
+ return script;
+ }
+
+ public int getLine() {
+ return line;
+ }
+
+ public int getColumn() {
+ return column;
+ }
+}
diff --git a/teavm-core/src/main/java/org/teavm/debugging/URLDebugInformationProvider.java b/teavm-core/src/main/java/org/teavm/debugging/URLDebugInformationProvider.java
new file mode 100644
index 000000000..8159a9cc4
--- /dev/null
+++ b/teavm-core/src/main/java/org/teavm/debugging/URLDebugInformationProvider.java
@@ -0,0 +1,44 @@
+/*
+ * 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.debugging;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ *
+ * @author Alexey Andreev
+ */
+public class URLDebugInformationProvider implements DebugInformationProvider {
+ private String baseURL;
+
+ public URLDebugInformationProvider(String baseURL) {
+ this.baseURL = baseURL;
+ }
+
+ @Override
+ public DebugInformation getDebugInformation(String script) {
+ try {
+ URL url = new URL(baseURL + script);
+ try (InputStream input = url.openStream()) {
+ return DebugInformation.read(input);
+ }
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}