mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Multiple small improvements
This commit is contained in:
parent
1b374c7466
commit
569d6fa3e8
|
@ -62,30 +62,45 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
|
||||
private ChromeRDPExchangeListener exchangeListener = new ChromeRDPExchangeListener() {
|
||||
@Override public void received(String messageText) throws IOException {
|
||||
JsonNode jsonMessage = mapper.readTree(messageText);
|
||||
if (jsonMessage.has("id")) {
|
||||
Response response = mapper.reader(Response.class).readValue(jsonMessage);
|
||||
responseHandlers.remove(response.getId()).received(response.getResult());
|
||||
} else {
|
||||
Message message = mapper.reader(Message.class).readValue(messageText);
|
||||
if (message.getMethod() == null) {
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
receiveMessage(messageText);
|
||||
}
|
||||
};
|
||||
|
||||
private void receiveMessage(final String messageText) {
|
||||
new Thread() {
|
||||
@Override public void run() {
|
||||
try {
|
||||
JsonNode jsonMessage = mapper.readTree(messageText);
|
||||
if (jsonMessage.has("id")) {
|
||||
Response response = mapper.reader(Response.class).readValue(jsonMessage);
|
||||
if (response.getError() != null) {
|
||||
System.err.println(response.getError().toString());
|
||||
}
|
||||
responseHandlers.remove(response.getId()).received(response.getResult());
|
||||
} else {
|
||||
Message message = mapper.reader(Message.class).readValue(messageText);
|
||||
if (message.getMethod() == null) {
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO: logging
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private synchronized void firePaused(SuspendedNotification params) {
|
||||
suspended = true;
|
||||
|
@ -256,8 +271,12 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
message.setParams(mapper.valueToTree(params));
|
||||
ResponseHandler handler = new ResponseHandler() {
|
||||
@Override public void received(JsonNode node) throws IOException {
|
||||
SetBreakpointResponse response = mapper.reader(SetBreakpointResponse.class).readValue(node);
|
||||
breakpoint.chromeId = response.getBreakpointId();
|
||||
if (node != null) {
|
||||
SetBreakpointResponse response = mapper.reader(SetBreakpointResponse.class).readValue(node);
|
||||
breakpoint.chromeId = response.getBreakpointId();
|
||||
} else {
|
||||
breakpoint.chromeId = null;
|
||||
}
|
||||
for (JavaScriptDebuggerListener listener : getListeners()) {
|
||||
listener.breakpointChanged(breakpoint);
|
||||
}
|
||||
|
@ -314,7 +333,8 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
sync.add("");
|
||||
} else {
|
||||
CallFunctionResponse response = mapper.reader(CallFunctionResponse.class).readValue(node);
|
||||
sync.add(response.getResult().getValue().getTextValue());
|
||||
RemoteObjectDTO result = response.getResult();
|
||||
sync.add(result.getValue() != null ? result.getValue().getTextValue() : "");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -327,6 +347,51 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
}
|
||||
}
|
||||
|
||||
String getRepresentation(String objectId) {
|
||||
if (exchange == null) {
|
||||
return null;
|
||||
}
|
||||
Message message = new Message();
|
||||
message.setId(messageIdGenerator.incrementAndGet());
|
||||
message.setMethod("Runtime.callFunctionOn");
|
||||
CallFunctionCommand params = new CallFunctionCommand();
|
||||
CallArgumentDTO arg = new CallArgumentDTO();
|
||||
arg.setObjectId(objectId);
|
||||
params.setObjectId(objectId);
|
||||
params.setArguments(new CallArgumentDTO[] { arg });
|
||||
params.setFunctionDeclaration("$dbg_repr");
|
||||
message.setParams(mapper.valueToTree(params));
|
||||
final BlockingQueue<RepresentationWrapper> sync = new LinkedTransferQueue<>();
|
||||
responseHandlers.put(message.getId(), new ResponseHandler() {
|
||||
@Override public void received(JsonNode node) throws IOException {
|
||||
if (node == null) {
|
||||
sync.add(new RepresentationWrapper(null));
|
||||
} else {
|
||||
CallFunctionResponse response = mapper.reader(CallFunctionResponse.class).readValue(node);
|
||||
RemoteObjectDTO result = response.getResult();
|
||||
sync.add(new RepresentationWrapper(result.getValue() != null ?
|
||||
result.getValue().getTextValue() : null));
|
||||
}
|
||||
}
|
||||
});
|
||||
sendMessage(message);
|
||||
try {
|
||||
RepresentationWrapper result = sync.take();
|
||||
return result.repr;
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class RepresentationWrapper {
|
||||
String repr;
|
||||
|
||||
public RepresentationWrapper(String repr) {
|
||||
super();
|
||||
this.repr = repr;
|
||||
}
|
||||
}
|
||||
|
||||
private List<RDPLocalVariable> parseProperties(PropertyDescriptorDTO[] properties) {
|
||||
List<RDPLocalVariable> variables = new ArrayList<>();
|
||||
if (properties != null) {
|
||||
|
@ -339,8 +404,7 @@ public class ChromeRDPDebugger implements JavaScriptDebugger, ChromeRDPExchangeC
|
|||
break;
|
||||
case "object":
|
||||
case "function":
|
||||
value = new RDPValue(this, remoteValue.getDescription(), remoteValue.getType(),
|
||||
remoteValue.getObjectId());
|
||||
value = new RDPValue(this, null, remoteValue.getType(), remoteValue.getObjectId());
|
||||
break;
|
||||
default:
|
||||
value = new RDPValue(this, remoteValue.getValue().asText(), remoteValue.getType(),
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.teavm.chromerdp;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import org.teavm.debugging.JavaScriptValue;
|
||||
import org.teavm.debugging.JavaScriptVariable;
|
||||
|
||||
|
@ -10,14 +11,15 @@ import org.teavm.debugging.JavaScriptVariable;
|
|||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class RDPValue implements JavaScriptValue {
|
||||
private String representation;
|
||||
private AtomicReference<String> representation = new AtomicReference<>();
|
||||
private AtomicReference<String> className = new AtomicReference<>();
|
||||
private String typeName;
|
||||
private ChromeRDPDebugger debugger;
|
||||
private String objectId;
|
||||
private Map<String, ? extends JavaScriptVariable> properties;
|
||||
|
||||
public RDPValue(ChromeRDPDebugger debugger, String representation, String typeName, String objectId) {
|
||||
this.representation = representation;
|
||||
this.representation.set(representation == null && objectId == null ? "" : representation);
|
||||
this.typeName = typeName;
|
||||
this.debugger = debugger;
|
||||
this.objectId = objectId;
|
||||
|
@ -27,17 +29,23 @@ public class RDPValue implements JavaScriptValue {
|
|||
|
||||
@Override
|
||||
public String getRepresentation() {
|
||||
return representation;
|
||||
if (representation.get() == null) {
|
||||
representation.compareAndSet(null, debugger.getRepresentation(objectId));
|
||||
}
|
||||
return representation.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getClassName() {
|
||||
if (objectId != null) {
|
||||
String className = debugger.getClassName(objectId);
|
||||
return className != null ? className : "object";
|
||||
} else {
|
||||
return typeName;
|
||||
if (className.get() == null) {
|
||||
if (objectId != null) {
|
||||
String computedClassName = debugger.getClassName(objectId);
|
||||
className.compareAndSet(null, computedClassName != null ? computedClassName : "@Object");
|
||||
} else {
|
||||
className.compareAndSet(null, "@" + typeName);
|
||||
}
|
||||
}
|
||||
return className.get();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
|||
public class Response {
|
||||
private int id;
|
||||
private JsonNode result;
|
||||
private JsonNode error;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
|
@ -42,4 +43,12 @@ public class Response {
|
|||
public void setResult(JsonNode result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public JsonNode getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(JsonNode error) {
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ public class JCLPlugin implements TeaVMPlugin {
|
|||
host.add(new EnumTransformer());
|
||||
host.add(new ClassLookupDependencySupport());
|
||||
host.add(new NewInstanceDependencySupport());
|
||||
host.add(new ObjectEnrichRenderer());
|
||||
ServiceLoaderSupport serviceLoaderSupp = new ServiceLoaderSupport(host.getClassLoader());
|
||||
host.add(serviceLoaderSupp);
|
||||
MethodReference loadServicesMethod = new MethodReference("java.util.ServiceLoader", new MethodDescriptor(
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.classlib.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.teavm.javascript.RenderingContext;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.spi.RendererListener;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class ObjectEnrichRenderer implements RendererListener {
|
||||
private RenderingContext context;
|
||||
|
||||
@Override
|
||||
public void begin(RenderingContext context, BuildTarget buildTarget) throws IOException {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeClass(ClassReader cls) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterClass(ClassReader cls) throws IOException {
|
||||
if (cls.getName().equals("java.lang.Object")) {
|
||||
MethodReader toString = cls.getMethod(new MethodDescriptor("toString", String.class));
|
||||
if (toString != null) {
|
||||
String clsName = context.getNaming().getNameFor(cls.getName());
|
||||
String toStringName = context.getNaming().getNameFor(toString.getReference());
|
||||
context.getWriter().append(clsName).append(".prototype.toString").ws().append('=').ws()
|
||||
.append("function()").ws().append('{').indent().softNewLine();
|
||||
context.getWriter().append("return this.").append(toStringName).ws().append('?').ws()
|
||||
.append("$rt_ustr(this.").append(toStringName).append("())").ws().append(':')
|
||||
.append("Object.prototype.toString.call(this);").softNewLine();
|
||||
context.getWriter().outdent().append("}").newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete() throws IOException {
|
||||
}
|
||||
}
|
|
@ -45,7 +45,7 @@ public class DebugInformation {
|
|||
Mapping methodMapping;
|
||||
Mapping lineMapping;
|
||||
MultiMapping[] variableMappings;
|
||||
List<Map<Integer, Integer>> classesMetadata;
|
||||
List<ClassMetadata> classesMetadata;
|
||||
|
||||
public String[] getCoveredSourceFiles() {
|
||||
return fileNames.clone();
|
||||
|
@ -130,8 +130,15 @@ public class DebugInformation {
|
|||
if (jsIndex == null) {
|
||||
return null;
|
||||
}
|
||||
Integer fieldIndex = classesMetadata.get(classIndex).get(jsIndex);
|
||||
return fieldIndex != null ? fields[fieldIndex] : null;
|
||||
while (classIndex != null) {
|
||||
ClassMetadata cls = classesMetadata.get(classIndex);
|
||||
Integer fieldIndex = cls.fieldMap.get(jsIndex);
|
||||
if (fieldIndex != null) {
|
||||
return fields[fieldIndex];
|
||||
}
|
||||
classIndex = cls.parentId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private <T> T componentByKey(Mapping mapping, T[] values, GeneratedLocation location) {
|
||||
|
@ -372,4 +379,9 @@ public class DebugInformation {
|
|||
return lines.length;
|
||||
}
|
||||
}
|
||||
|
||||
static class ClassMetadata {
|
||||
Integer parentId;
|
||||
Map<Integer, Integer> fieldMap = new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,12 +104,14 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addClass(String className) {
|
||||
public void addClass(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;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -140,13 +142,16 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
debugInformation.variableMappings[var] = mapping.build();
|
||||
}
|
||||
|
||||
List<Map<Integer, Integer>> builtMetadata = new ArrayList<>(classes.list.size());
|
||||
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 HashMap<Integer, Integer>());
|
||||
builtMetadata.add(new DebugInformation.ClassMetadata());
|
||||
} else {
|
||||
Map<Integer, Integer> map = new HashMap<>(classesMetadata.get(i).fieldMap);
|
||||
builtMetadata.add(map);
|
||||
ClassMetadata origMetadata = classesMetadata.get(i);
|
||||
DebugInformation.ClassMetadata mappedMetadata = new DebugInformation.ClassMetadata();
|
||||
mappedMetadata.fieldMap.putAll(origMetadata.fieldMap);
|
||||
mappedMetadata.parentId = origMetadata.parentIndex >= 0 ? origMetadata.parentIndex : null;
|
||||
builtMetadata.add(mappedMetadata);
|
||||
}
|
||||
}
|
||||
debugInformation.classesMetadata = builtMetadata;
|
||||
|
@ -285,6 +290,7 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
}
|
||||
|
||||
static class ClassMetadata {
|
||||
int parentIndex;
|
||||
Map<Integer, Integer> fieldMap = new HashMap<>();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public interface DebugInformationEmitter {
|
|||
|
||||
void emitVariable(String[] sourceNames, String generatedName);
|
||||
|
||||
void addClass(String className);
|
||||
void addClass(String className, String parentName);
|
||||
|
||||
void addField(String fieldName, String jsName);
|
||||
}
|
|
@ -19,9 +19,7 @@ import java.io.EOFException;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -64,17 +62,21 @@ class DebugInformationReader {
|
|||
return mappings;
|
||||
}
|
||||
|
||||
private List<Map<Integer, Integer>> readClassesMetadata(int count) throws IOException {
|
||||
List<Map<Integer, Integer>> classes = new ArrayList<>(count);
|
||||
private List<DebugInformation.ClassMetadata> readClassesMetadata(int count) throws IOException {
|
||||
List<DebugInformation.ClassMetadata> classes = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
Map<Integer, Integer> cls = new HashMap<>();
|
||||
DebugInformation.ClassMetadata cls = new DebugInformation.ClassMetadata();
|
||||
classes.add(cls);
|
||||
cls.parentId = readUnsignedNumber() - 1;
|
||||
if (cls.parentId.equals(-1)) {
|
||||
cls.parentId = null;
|
||||
}
|
||||
int entryCount = readUnsignedNumber();
|
||||
resetRelativeNumber();
|
||||
for (int j = 0; j < entryCount; ++j) {
|
||||
int key = readRelativeNumber();
|
||||
int value = readUnsignedNumber();
|
||||
cls.put(key, value);
|
||||
cls.fieldMap.put(key, value);
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
|
|
|
@ -20,7 +20,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.debugging.DebugInformation.ClassMetadata;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -63,16 +63,17 @@ class DebugInformationWriter {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeClassMetadata(List<Map<Integer, Integer>> classes) throws IOException {
|
||||
private void writeClassMetadata(List<ClassMetadata> classes) throws IOException {
|
||||
for (int i = 0; i < classes.size(); ++i) {
|
||||
Map<Integer, Integer> cls = classes.get(i);
|
||||
writeUnsignedNumber(cls.size());
|
||||
List<Integer> keys = new ArrayList<>(cls.keySet());
|
||||
ClassMetadata cls = classes.get(i);
|
||||
writeUnsignedNumber(cls.parentId != null ? cls.parentId + 1 : 0);
|
||||
writeUnsignedNumber(cls.fieldMap.size());
|
||||
List<Integer> keys = new ArrayList<>(cls.fieldMap.keySet());
|
||||
Collections.sort(keys);
|
||||
resetRelativeNumber();
|
||||
for (int key : keys) {
|
||||
writeRelativeNumber(key);
|
||||
writeUnsignedNumber(cls.get(key));
|
||||
writeUnsignedNumber(cls.fieldMap.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,6 @@ import org.teavm.model.MethodReference;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
// TODO: variable name handling
|
||||
// TODO: class fields handling
|
||||
public class Debugger {
|
||||
private static final Object dummyObject = new Object();
|
||||
private ConcurrentMap<DebuggerListener, Object> listeners = new ConcurrentHashMap<>();
|
||||
|
@ -198,13 +196,16 @@ public class Debugger {
|
|||
|
||||
private void addScript(String name) {
|
||||
if (debugInformationMap.containsKey(name)) {
|
||||
updateBreakpoints();
|
||||
return;
|
||||
}
|
||||
DebugInformation debugInfo = debugInformationProvider.getDebugInformation(name);
|
||||
if (debugInfo == null) {
|
||||
updateBreakpoints();
|
||||
return;
|
||||
}
|
||||
if (debugInformationMap.putIfAbsent(name, debugInfo) != null) {
|
||||
updateBreakpoints();
|
||||
return;
|
||||
}
|
||||
for (String sourceFile : debugInfo.getCoveredSourceFiles()) {
|
||||
|
@ -220,6 +221,10 @@ public class Debugger {
|
|||
list.put(debugInfo, dummyObject);
|
||||
}
|
||||
scriptMap.put(debugInfo, name);
|
||||
updateBreakpoints();
|
||||
}
|
||||
|
||||
private void updateBreakpoints() {
|
||||
for (Breakpoint breakpoint : breakpoints.keySet()) {
|
||||
updateInternalBreakpoints(breakpoint);
|
||||
updateBreakpointStatus(breakpoint, true);
|
||||
|
|
|
@ -45,7 +45,7 @@ public class DummyDebugInformationEmitter implements DebugInformationEmitter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addClass(String className) {
|
||||
public void addClass(String className, String parentName) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -243,7 +243,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
|
|||
|
||||
public void render(ClassNode cls) throws RenderingException {
|
||||
debugEmitter.emitClass(cls.getName());
|
||||
debugEmitter.addClass(cls.getName());
|
||||
debugEmitter.addClass(cls.getName(), cls.getParentName());
|
||||
try {
|
||||
writer.append("function ").appendClass(cls.getName()).append("()").ws().append("{")
|
||||
.indent().softNewLine();
|
||||
|
|
|
@ -108,6 +108,17 @@ $rt_arraycls = function(cls) {
|
|||
};
|
||||
arraycls.prototype = new ($rt_objcls())();
|
||||
arraycls.prototype.constructor = arraycls;
|
||||
arraycls.prototype.toString = function() {
|
||||
var str = "[";
|
||||
for (var i = 0; i < this.data.length; ++i) {
|
||||
if (i > 0) {
|
||||
str += ", ";
|
||||
}
|
||||
str += this.data[i].toString();
|
||||
}
|
||||
str += "]";
|
||||
return str;
|
||||
}
|
||||
arraycls.$meta = { item : cls, supertypes : [$rt_objcls()], primitive : false, superclass : $rt_objcls() };
|
||||
cls.$array = arraycls;
|
||||
}
|
||||
|
@ -392,20 +403,64 @@ function $rt_s(index) {
|
|||
}
|
||||
|
||||
function $dbg_repr(obj) {
|
||||
return obj.toString();
|
||||
return obj.toString ? obj.toString() : "";
|
||||
}
|
||||
function $dbg_class(obj) {
|
||||
if (obj instanceof Long) {
|
||||
return "long";
|
||||
}
|
||||
var meta = obj.constructor.$meta;
|
||||
return meta ? meta.name : "";
|
||||
var cls = obj.constructor;
|
||||
var arrayDegree = 0;
|
||||
while (cls.$meta && cls.$meta.item) {
|
||||
++arrayDegree;
|
||||
cls = cls.$meta.item;
|
||||
}
|
||||
var clsName = "";
|
||||
if (cls === $rt_booleancls()) {
|
||||
clsName = "boolean";
|
||||
} else if (cls === $rt_bytecls()) {
|
||||
clsName = "byte";
|
||||
} else if (cls === $rt_shortcls()) {
|
||||
clsName = "short";
|
||||
} else if (cls === $rt_charcls()) {
|
||||
clsName = "char";
|
||||
} else if (cls === $rt_intcls()) {
|
||||
clsName = "int";
|
||||
} else if (cls === $rt_longcls()) {
|
||||
clsName = "long";
|
||||
} else if (cls === $rt_floatcls()) {
|
||||
clsName = "float";
|
||||
} else if (cls === $rt_doublecls()) {
|
||||
clsName = "double";
|
||||
} else {
|
||||
clsName = cls.$meta ? cls.$meta.name : "@" + cls.name;
|
||||
}
|
||||
while (arrayDegree-- > 0) {
|
||||
clsName += "[]";
|
||||
}
|
||||
return clsName;
|
||||
}
|
||||
|
||||
Long = function(lo, hi) {
|
||||
this.lo = lo | 0;
|
||||
this.hi = hi | 0;
|
||||
}
|
||||
Long.prototype.toString = function() {
|
||||
var result = [];
|
||||
var n = this;
|
||||
var positive = Long_isPositive(n);
|
||||
if (!positive) {
|
||||
n = Long_neg(n);
|
||||
}
|
||||
var radix = new Long(10, 0);
|
||||
do {
|
||||
var divRem = Long_divRem(n, radix);
|
||||
result.push(String.fromCharCode(48 + divRem[1].lo));
|
||||
n = divRem[0];
|
||||
} while (n.lo != 0 || n.hi != 0);
|
||||
result = result.reverse().join('');
|
||||
return positive ? result : "-" + result;
|
||||
}
|
||||
Long_ZERO = new Long(0, 0);
|
||||
Long_fromInt = function(val) {
|
||||
return val >= 0 ? new Long(val, 0) : new Long(val, -1);
|
||||
|
|
Loading…
Reference in New Issue
Block a user