Fix calculating class name in debugger

This commit is contained in:
Alexey Andreev 2018-11-19 15:29:02 +03:00
parent f2dd398719
commit 0f951f8c86
12 changed files with 96 additions and 23 deletions

View File

@ -272,9 +272,10 @@ public class Renderer implements RenderingManager {
}
private void renderDeclaration(ClassNode cls) throws RenderingException {
debugEmitter.addClass(cls.getName(), cls.getParentName());
String jsName = writer.getNaming().getNameFor(cls.getName());
debugEmitter.addClass(jsName, cls.getName(), cls.getParentName());
try {
writer.append("function ").appendClass(cls.getName()).append("()").ws().append("{")
writer.append("function " + jsName + "()").ws().append("{")
.indent().softNewLine();
boolean thisAliased = false;
List<FieldNode> nonStaticFields = new ArrayList<>();

View File

@ -302,7 +302,8 @@ public class Debugger {
MethodReference method = !empty ? debugInformation.getMethodAt(jsFrame.getLocation().getLine(),
jsFrame.getLocation().getColumn()) : null;
if (!empty || !wasEmpty) {
VariableMap vars = new VariableMap(jsFrame.getVariables(), this, jsFrame.getLocation());
VariableMap vars = new VariableMap(jsFrame.getVariables(), this, debugInformation,
jsFrame.getLocation());
frames.add(new CallFrame(this, jsFrame, loc, method, vars));
}
wasEmpty = empty;

View File

@ -19,6 +19,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.teavm.debugging.information.DebugInformation;
import org.teavm.debugging.javascript.JavaScriptVariable;
class PropertyMap extends AbstractMap<String, Variable> {
@ -26,11 +27,14 @@ class PropertyMap extends AbstractMap<String, Variable> {
private AtomicReference<Map<String, Variable>> backingMap = new AtomicReference<>();
private Map<String, JavaScriptVariable> jsVariables;
private Debugger debugger;
private DebugInformation debugInformation;
public PropertyMap(String className, Map<String, JavaScriptVariable> jsVariables, Debugger debugger) {
public PropertyMap(String className, Map<String, JavaScriptVariable> jsVariables, Debugger debugger,
DebugInformation debugInformation) {
this.className = className;
this.jsVariables = jsVariables;
this.debugger = debugger;
this.debugInformation = debugInformation;
}
@Override
@ -73,7 +77,7 @@ class PropertyMap extends AbstractMap<String, Variable> {
continue;
}
}
Value value = new Value(debugger, jsVar.getValue());
Value value = new Value(debugger, debugInformation, jsVar.getValue());
vars.put(name, new Variable(name, value));
}
backingMap.compareAndSet(null, vars);

View File

@ -17,15 +17,18 @@ package org.teavm.debugging;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.teavm.debugging.information.DebugInformation;
import org.teavm.debugging.javascript.JavaScriptValue;
public class Value {
private Debugger debugger;
private DebugInformation debugInformation;
private JavaScriptValue jsValue;
private AtomicReference<PropertyMap> properties = new AtomicReference<>();
Value(Debugger debugger, JavaScriptValue jsValue) {
Value(Debugger debugger, DebugInformation debugInformation, JavaScriptValue jsValue) {
this.debugger = debugger;
this.debugInformation = debugInformation;
this.jsValue = jsValue;
}
@ -34,12 +37,23 @@ public class Value {
}
public String getType() {
return jsValue.getClassName();
String className = jsValue.getClassName();
if (className.startsWith("a/")) {
className = className.substring(2);
String javaClassName = debugInformation.getClassNameByJsName(className);
if (javaClassName != null) {
className = javaClassName;
}
} else if (className.startsWith("@")) {
className = className.substring(1);
}
return className;
}
public Map<String, Variable> getProperties() {
if (properties.get() == null) {
properties.compareAndSet(null, new PropertyMap(jsValue.getClassName(), jsValue.getProperties(), debugger));
properties.compareAndSet(null, new PropertyMap(jsValue.getClassName(), jsValue.getProperties(), debugger,
debugInformation));
}
return properties.get();
}

View File

@ -20,6 +20,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.teavm.debugging.information.DebugInformation;
import org.teavm.debugging.javascript.JavaScriptLocation;
import org.teavm.debugging.javascript.JavaScriptVariable;
@ -27,11 +28,14 @@ class VariableMap extends AbstractMap<String, Variable> {
private AtomicReference<Map<String, Variable>> backingMap = new AtomicReference<>();
private Map<String, JavaScriptVariable> jsVariables;
private Debugger debugger;
private DebugInformation debugInformation;
private JavaScriptLocation location;
public VariableMap(Map<String, JavaScriptVariable> jsVariables, Debugger debugger, JavaScriptLocation location) {
public VariableMap(Map<String, JavaScriptVariable> jsVariables, Debugger debugger,
DebugInformation debugInformation, JavaScriptLocation location) {
this.jsVariables = jsVariables;
this.debugger = debugger;
this.debugInformation = debugInformation;
this.location = location;
}
@ -61,7 +65,7 @@ class VariableMap extends AbstractMap<String, Variable> {
for (Map.Entry<String, JavaScriptVariable> entry : jsVariables.entrySet()) {
JavaScriptVariable jsVar = entry.getValue();
String[] names = debugger.mapVariable(entry.getKey(), location);
Value value = new Value(debugger, jsVar.getValue());
Value value = new Value(debugger, debugInformation, jsVar.getValue());
for (String name : names) {
if (name == null) {
name = "js:" + jsVar.getName();

View File

@ -47,6 +47,7 @@ public class DebugInformation {
RecordArray[] lineCallSites;
RecordArray[] controlFlowGraphs;
List<ClassMetadata> classesMetadata;
Map<String, ClassMetadata> classMetadataByJsName;
RecordArray methodEntrances;
MethodTree methodTree;
@ -270,6 +271,11 @@ public class DebugInformation {
return null;
}
public String getClassNameByJsName(String className) {
ClassMetadata cls = classMetadataByJsName.get(className);
return cls != null ? classNames[cls.id] : null;
}
public DebuggerCallSite getCallSite(GeneratedLocation location) {
int keyIndex = indexByKey(callSiteMapping, location);
return keyIndex >= 0 ? getCallSite(keyIndex) : null;
@ -411,6 +417,7 @@ public class DebugInformation {
rebuildEntrances();
rebuildMethodTree();
rebuildLineCallSites();
rebuildClassMap();
}
void rebuildMaps() {
@ -594,6 +601,15 @@ public class DebugInformation {
return new GeneratedLocation(record.get(0), record.get(1));
}
private void rebuildClassMap() {
classMetadataByJsName = new HashMap<>();
for (DebugInformation.ClassMetadata cls : classesMetadata) {
if (cls.jsName != null) {
classMetadataByJsName.put(cls.jsName, cls);
}
}
}
private int binarySearchLocation(RecordArray array, int row, int column) {
int l = 0;
int u = array.size() - 1;
@ -640,9 +656,11 @@ public class DebugInformation {
}
static class ClassMetadata {
int id;
Integer parentId;
Map<Integer, Integer> fieldMap = new HashMap<>();
int[] methods;
String jsName;
}
class MethodTree {

View File

@ -177,14 +177,17 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
}
@Override
public void addClass(String className, String parentName) {
public void addClass(String jsName, String className, String parentName) {
int classIndex = classes.index(className);
int parentIndex = classes.index(parentName);
while (classIndex >= classesMetadata.size()) {
classesMetadata.add(new ClassMetadata());
}
currentClassMetadata = classIndex;
classesMetadata.get(currentClassMetadata).parentIndex = parentIndex;
ClassMetadata metadata = classesMetadata.get(classIndex);
metadata.parentIndex = parentIndex;
metadata.jsName = jsName;
}
@Override
@ -288,15 +291,15 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
List<DebugInformation.ClassMetadata> builtMetadata = new ArrayList<>(classes.list.size());
for (int i = 0; i < classes.list.size(); ++i) {
if (i >= classesMetadata.size()) {
builtMetadata.add(new DebugInformation.ClassMetadata());
} else {
DebugInformation.ClassMetadata mappedMetadata = new DebugInformation.ClassMetadata();
mappedMetadata.id = i;
if (i < classesMetadata.size()) {
ClassMetadata origMetadata = classesMetadata.get(i);
DebugInformation.ClassMetadata mappedMetadata = new DebugInformation.ClassMetadata();
mappedMetadata.jsName = origMetadata.jsName;
mappedMetadata.fieldMap.putAll(origMetadata.fieldMap);
mappedMetadata.parentId = origMetadata.parentIndex >= 0 ? origMetadata.parentIndex : null;
builtMetadata.add(mappedMetadata);
}
builtMetadata.add(mappedMetadata);
}
debugInformation.classesMetadata = builtMetadata;
@ -340,6 +343,7 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
static class ClassMetadata {
int parentIndex;
String jsName;
Map<Integer, Integer> fieldMap = new HashMap<>();
}
}

View File

@ -33,7 +33,7 @@ public interface DebugInformationEmitter {
DeferredCallSite emitCallSite();
void addClass(String className, String parentName);
void addClass(String jsName, String className, String parentName);
void addField(String fieldName, String jsName);

View File

@ -18,6 +18,7 @@ package org.teavm.debugging.information;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import org.teavm.common.RecordArray;
@ -68,6 +69,8 @@ class DebugInformationReader {
for (int i = 0; i < count; ++i) {
DebugInformation.ClassMetadata cls = new DebugInformation.ClassMetadata();
classes.add(cls);
cls.id = i;
cls.jsName = readNullableString();
cls.parentId = readUnsignedNumber() - 1;
if (cls.parentId.equals(-1)) {
cls.parentId = null;
@ -322,7 +325,16 @@ class DebugInformationReader {
}
private String readString() throws IOException {
byte[] bytes = new byte[readUnsignedNumber()];
return readStringChars(readUnsignedNumber());
}
private String readNullableString() throws IOException {
int size = readUnsignedNumber();
return size > 0 ? readStringChars(size - 1) : null;
}
private String readStringChars(int size) throws IOException {
byte[] bytes = new byte[size];
int pos = 0;
while (pos < bytes.length) {
int read = input.read(bytes, pos, bytes.length - pos);
@ -331,6 +343,6 @@ class DebugInformationReader {
}
pos += read;
}
return new String(bytes, "UTF-8");
return new String(bytes, StandardCharsets.UTF_8);
}
}

View File

@ -17,6 +17,7 @@ package org.teavm.debugging.information;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -69,6 +70,7 @@ class DebugInformationWriter {
private void writeClassMetadata(List<ClassMetadata> classes) throws IOException {
for (int i = 0; i < classes.size(); ++i) {
ClassMetadata cls = classes.get(i);
writeNullableString(cls.jsName);
writeUnsignedNumber(cls.parentId != null ? cls.parentId + 1 : 0);
writeUnsignedNumber(cls.fieldMap.size());
List<Integer> keys = new ArrayList<>(cls.fieldMap.keySet());
@ -295,8 +297,18 @@ class DebugInformationWriter {
}
private void writeString(String str) throws IOException {
byte[] bytes = str.getBytes("UTF-8");
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
writeUnsignedNumber(bytes.length);
output.write(bytes);
}
private void writeNullableString(String str) throws IOException {
if (str == null) {
writeUnsignedNumber(0);
return;
}
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
writeUnsignedNumber(bytes.length + 1);
output.write(bytes);
}
}

View File

@ -54,7 +54,7 @@ public class DummyDebugInformationEmitter implements DebugInformationEmitter {
}
@Override
public void addClass(String className, String parentName) {
public void addClass(String jsName, String className, String parentName) {
}
@Override

View File

@ -204,6 +204,9 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
if (scripts.putIfAbsent(params.getScriptId(), params.getUrl()) != null) {
return;
}
if (params.getUrl().equals("file://fake")) {
return;
}
scriptIds.put(params.getUrl(), params.getScriptId());
for (JavaScriptDebuggerListener listener : getListeners()) {
listener.scriptAdded(params.getUrl());
@ -355,7 +358,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
breakpoint.updating.set(true);
try {
SetBreakpointResponse response = callMethod("Debugger.setBreakpoint", SetBreakpointResponse.class, params);
if (response == null) {
if (response != null) {
breakpoint.chromeId = response.getBreakpointId();
if (breakpoint.chromeId != null) {
breakpointsByChromeId.put(breakpoint.chromeId, breakpoint);