mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Place classes to a single object in development server to improve debugger performance
This commit is contained in:
parent
95a3a30a6e
commit
1b2c47407f
|
@ -147,7 +147,7 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
|
||||||
writer.appendClass(className).append(".$meta.fields").ws().append('=').ws().append('[').indent();
|
writer.appendClass(className).append(".$meta.fields").ws().append('=').ws().append('[').indent();
|
||||||
|
|
||||||
generateCreateMembers(writer, cls.getFields(), field -> {
|
generateCreateMembers(writer, cls.getFields(), field -> {
|
||||||
appendProperty(writer, "type", false, () -> writer.append(context.typeToClassString(field.getType())));
|
appendProperty(writer, "type", false, () -> context.typeToClassString(writer, field.getType()));
|
||||||
|
|
||||||
appendProperty(writer, "getter", false, () -> {
|
appendProperty(writer, "getter", false, () -> {
|
||||||
if (accessibleFields != null && accessibleFields.contains(field.getName())) {
|
if (accessibleFields != null && accessibleFields.contains(field.getName())) {
|
||||||
|
@ -188,13 +188,13 @@ public class ClassGenerator implements Generator, Injector, DependencyPlugin {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
writer.append(',').ws();
|
writer.append(',').ws();
|
||||||
}
|
}
|
||||||
writer.append(context.typeToClassString(method.parameterType(i)));
|
context.typeToClassString(writer, method.parameterType(i));
|
||||||
}
|
}
|
||||||
writer.append(']');
|
writer.append(']');
|
||||||
});
|
});
|
||||||
|
|
||||||
appendProperty(writer, "returnType", false, () -> {
|
appendProperty(writer, "returnType", false, () -> {
|
||||||
writer.append(context.typeToClassString(method.getResultType()));
|
context.typeToClassString(writer, method.getResultType());
|
||||||
});
|
});
|
||||||
|
|
||||||
appendProperty(writer, "callable", false, () -> {
|
appendProperty(writer, "callable", false, () -> {
|
||||||
|
|
|
@ -358,6 +358,10 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
||||||
|
|
||||||
renderer.prepare(clsNodes);
|
renderer.prepare(clsNodes);
|
||||||
runtimeRenderer.renderRuntime();
|
runtimeRenderer.renderRuntime();
|
||||||
|
if (classScoped) {
|
||||||
|
sourceWriter.append("var ").append(Renderer.CONTAINER_OBJECT).ws().append("=").ws()
|
||||||
|
.append("Object.create(null);").newLine();
|
||||||
|
}
|
||||||
if (!renderer.render(clsNodes)) {
|
if (!renderer.render(clsNodes)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package org.teavm.backend.javascript.codegen;
|
package org.teavm.backend.javascript.codegen;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.teavm.backend.javascript.rendering.Renderer;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
@ -101,11 +102,12 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendClass(String cls) throws IOException {
|
public SourceWriter appendClass(String cls) throws IOException {
|
||||||
|
appendScopeIfNecessary();
|
||||||
return append(naming.getNameFor(cls));
|
return append(naming.getNameFor(cls));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendClass(Class<?> cls) throws IOException {
|
public SourceWriter appendClass(Class<?> cls) throws IOException {
|
||||||
return append(naming.getNameFor(cls.getName()));
|
return appendClass(cls.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendField(FieldReference field) throws IOException {
|
public SourceWriter appendField(FieldReference field) throws IOException {
|
||||||
|
@ -113,7 +115,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendStaticField(FieldReference field) throws IOException {
|
public SourceWriter appendStaticField(FieldReference field) throws IOException {
|
||||||
appendClassScopeIfNecessary(field.getClassName());
|
appendScopeIfNecessary();
|
||||||
return append(naming.getFullNameFor(field));
|
return append(naming.getFullNameFor(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +128,7 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendMethodBody(MethodReference method) throws IOException {
|
public SourceWriter appendMethodBody(MethodReference method) throws IOException {
|
||||||
appendClassScopeIfNecessary(method.getClassName());
|
appendScopeIfNecessary();
|
||||||
return append(naming.getFullNameFor(method));
|
return append(naming.getFullNameFor(method));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,18 +145,18 @@ public class SourceWriter implements Appendable, LocationProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendInit(MethodReference method) throws IOException {
|
public SourceWriter appendInit(MethodReference method) throws IOException {
|
||||||
appendClassScopeIfNecessary(method.getClassName());
|
appendScopeIfNecessary();
|
||||||
return append(naming.getNameForInit(method));
|
return append(naming.getNameForInit(method));
|
||||||
}
|
}
|
||||||
|
|
||||||
public SourceWriter appendClassInit(String className) throws IOException {
|
public SourceWriter appendClassInit(String className) throws IOException {
|
||||||
appendClassScopeIfNecessary(className);
|
appendScopeIfNecessary();
|
||||||
return append(naming.getNameForClassInit(className));
|
return append(naming.getNameForClassInit(className));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void appendClassScopeIfNecessary(String className) throws IOException {
|
private void appendScopeIfNecessary() throws IOException {
|
||||||
if (classScoped) {
|
if (classScoped) {
|
||||||
append(naming.getNameFor(className)).append(".");
|
append(Renderer.CONTAINER_OBJECT).append(".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ import org.teavm.vm.RenderingException;
|
||||||
import org.teavm.vm.TeaVMProgressFeedback;
|
import org.teavm.vm.TeaVMProgressFeedback;
|
||||||
|
|
||||||
public class Renderer implements RenderingManager {
|
public class Renderer implements RenderingManager {
|
||||||
|
public static final String CONTAINER_OBJECT = "$java";
|
||||||
private final NamingStrategy naming;
|
private final NamingStrategy naming;
|
||||||
private final SourceWriter writer;
|
private final SourceWriter writer;
|
||||||
private final ListableClassReaderSource classSource;
|
private final ListableClassReaderSource classSource;
|
||||||
|
@ -198,8 +199,9 @@ public class Renderer implements RenderingManager {
|
||||||
try {
|
try {
|
||||||
for (PostponedFieldInitializer initializer : postponedFieldInitializers) {
|
for (PostponedFieldInitializer initializer : postponedFieldInitializers) {
|
||||||
int start = writer.getOffset();
|
int start = writer.getOffset();
|
||||||
writer.appendStaticField(initializer.field).ws().append("=").ws()
|
writer.appendStaticField(initializer.field).ws().append("=").ws();
|
||||||
.append(context.constantToString(initializer.value)).append(";").softNewLine();
|
context.constantToString(writer, initializer.value);
|
||||||
|
writer.append(";").softNewLine();
|
||||||
int sz = writer.getOffset() - start;
|
int sz = writer.getOffset() - start;
|
||||||
appendClassSize(initializer.field.getClassName(), sz);
|
appendClassSize(initializer.field.getClassName(), sz);
|
||||||
}
|
}
|
||||||
|
@ -299,7 +301,8 @@ public class Renderer implements RenderingManager {
|
||||||
String jsName = naming.getNameFor(cls.getName());
|
String jsName = naming.getNameFor(cls.getName());
|
||||||
debugEmitter.addClass(jsName, cls.getName(), cls.getParentName());
|
debugEmitter.addClass(jsName, cls.getName(), cls.getParentName());
|
||||||
try {
|
try {
|
||||||
writer.append("function " + jsName + "()").ws().append("{")
|
renderFunctionDeclaration(jsName);
|
||||||
|
writer.append("()").ws().append("{")
|
||||||
.indent().softNewLine();
|
.indent().softNewLine();
|
||||||
boolean thisAliased = false;
|
boolean thisAliased = false;
|
||||||
List<FieldNode> nonStaticFields = new ArrayList<>();
|
List<FieldNode> nonStaticFields = new ArrayList<>();
|
||||||
|
@ -326,7 +329,9 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
|
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
|
||||||
writer.append(thisAliased ? "a" : "this").append(".").appendField(fieldRef).ws()
|
writer.append(thisAliased ? "a" : "this").append(".").appendField(fieldRef).ws()
|
||||||
.append("=").ws().append(context.constantToString(value)).append(";").softNewLine();
|
.append("=").ws();
|
||||||
|
context.constantToString(writer, value);
|
||||||
|
writer.append(";").softNewLine();
|
||||||
debugEmitter.addField(field.getName(), naming.getNameFor(fieldRef));
|
debugEmitter.addField(field.getName(), naming.getNameFor(fieldRef));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +339,11 @@ public class Renderer implements RenderingManager {
|
||||||
writer.append("this.$id$").ws().append('=').ws().append("0;").softNewLine();
|
writer.append("this.$id$").ws().append('=').ws().append("0;").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}");
|
||||||
|
if (classScoped) {
|
||||||
|
writer.append(";");
|
||||||
|
}
|
||||||
|
writer.newLine();
|
||||||
|
|
||||||
for (FieldNode field : staticFields) {
|
for (FieldNode field : staticFields) {
|
||||||
Object value = field.getInitialValue();
|
Object value = field.getInitialValue();
|
||||||
|
@ -343,17 +352,18 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
|
FieldReference fieldRef = new FieldReference(cls.getName(), field.getName());
|
||||||
if (value instanceof String) {
|
if (value instanceof String) {
|
||||||
context.constantToString(value);
|
context.lookupString((String) value);
|
||||||
postponedFieldInitializers.add(new PostponedFieldInitializer(fieldRef, (String) value));
|
postponedFieldInitializers.add(new PostponedFieldInitializer(fieldRef, (String) value));
|
||||||
value = null;
|
value = null;
|
||||||
}
|
}
|
||||||
if (classScoped) {
|
if (classScoped) {
|
||||||
writer.append(jsName).append(".");
|
writer.append(CONTAINER_OBJECT).append(".");
|
||||||
} else {
|
} else {
|
||||||
writer.append("var ");
|
writer.append("var ");
|
||||||
}
|
}
|
||||||
writer.append(naming.getFullNameFor(fieldRef)).ws().append("=").ws()
|
writer.append(naming.getFullNameFor(fieldRef)).ws().append("=").ws();
|
||||||
.append(context.constantToString(value)).append(";").softNewLine();
|
context.constantToString(writer, value);
|
||||||
|
writer.append(";").softNewLine();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RenderingException("IO error occurred", e);
|
throw new RenderingException("IO error occurred", e);
|
||||||
|
@ -373,14 +383,14 @@ public class Renderer implements RenderingManager {
|
||||||
for (MethodNode method : cls.getMethods()) {
|
for (MethodNode method : cls.getMethods()) {
|
||||||
if (!method.getModifiers().contains(ElementModifier.STATIC)) {
|
if (!method.getModifiers().contains(ElementModifier.STATIC)) {
|
||||||
if (method.getReference().getName().equals("<init>")) {
|
if (method.getReference().getName().equals("<init>")) {
|
||||||
renderInitializer(cls.getName(), method);
|
renderInitializer(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MethodNode method : cls.getMethods()) {
|
for (MethodNode method : cls.getMethods()) {
|
||||||
renderBody(cls.getName(), method);
|
renderBody(method);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RenderingException("IO error occurred", e);
|
throw new RenderingException("IO error occurred", e);
|
||||||
|
@ -392,12 +402,12 @@ public class Renderer implements RenderingManager {
|
||||||
throws IOException {
|
throws IOException {
|
||||||
boolean isAsync = asyncMethods.contains(clinit.getReference());
|
boolean isAsync = asyncMethods.contains(clinit.getReference());
|
||||||
|
|
||||||
|
String clinitCalled = naming.getNameFor(cls.getName() + "_$clinitCalled");
|
||||||
if (isAsync) {
|
if (isAsync) {
|
||||||
writer.append("var ").appendClass(cls.getName()).append("_$clinitCalled").ws().append("=").ws()
|
writer.append("var ").append(clinitCalled).ws().append("=").ws().append("false;").softNewLine();
|
||||||
.append("false;").softNewLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderFunctionDeclaration(cls.getName(), naming.getNameForClassInit(cls.getName()));
|
renderFunctionDeclaration(naming.getNameForClassInit(cls.getName()));
|
||||||
writer.append("()").ws()
|
writer.append("()").ws()
|
||||||
.append("{").softNewLine().indent();
|
.append("{").softNewLine().indent();
|
||||||
|
|
||||||
|
@ -417,8 +427,7 @@ public class Renderer implements RenderingManager {
|
||||||
renderAsyncPrologue();
|
renderAsyncPrologue();
|
||||||
|
|
||||||
writer.append("case 0:").indent().softNewLine();
|
writer.append("case 0:").indent().softNewLine();
|
||||||
writer.appendClass(cls.getName()).append("_$clinitCalled").ws().append('=').ws().append("true;")
|
writer.append(clinitCalled).ws().append('=').ws().append("true;").softNewLine();
|
||||||
.softNewLine();
|
|
||||||
} else {
|
} else {
|
||||||
renderEraseClinit(cls);
|
renderEraseClinit(cls);
|
||||||
}
|
}
|
||||||
|
@ -690,10 +699,10 @@ public class Renderer implements RenderingManager {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderInitializer(String className, MethodNode method) throws IOException {
|
private void renderInitializer(MethodNode method) throws IOException {
|
||||||
MethodReference ref = method.getReference();
|
MethodReference ref = method.getReference();
|
||||||
debugEmitter.emitMethod(ref.getDescriptor());
|
debugEmitter.emitMethod(ref.getDescriptor());
|
||||||
renderFunctionDeclaration(className, naming.getNameForInit(ref));
|
renderFunctionDeclaration(naming.getNameForInit(ref));
|
||||||
writer.append("(");
|
writer.append("(");
|
||||||
for (int i = 0; i < ref.parameterCount(); ++i) {
|
for (int i = 0; i < ref.parameterCount(); ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
|
@ -774,7 +783,7 @@ public class Renderer implements RenderingManager {
|
||||||
writer.append(");").ws().append("}");
|
writer.append(");").ws().append("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderBody(String className, MethodNode method) throws IOException {
|
private void renderBody(MethodNode method) throws IOException {
|
||||||
StatementRenderer statementRenderer = new StatementRenderer(context, writer);
|
StatementRenderer statementRenderer = new StatementRenderer(context, writer);
|
||||||
statementRenderer.setCurrentMethod(method);
|
statementRenderer.setCurrentMethod(method);
|
||||||
|
|
||||||
|
@ -782,7 +791,7 @@ public class Renderer implements RenderingManager {
|
||||||
debugEmitter.emitMethod(ref.getDescriptor());
|
debugEmitter.emitMethod(ref.getDescriptor());
|
||||||
String name = naming.getFullNameFor(ref);
|
String name = naming.getFullNameFor(ref);
|
||||||
|
|
||||||
renderFunctionDeclaration(className, name);
|
renderFunctionDeclaration(name);
|
||||||
writer.append("(");
|
writer.append("(");
|
||||||
int startParam = 0;
|
int startParam = 0;
|
||||||
if (method.getModifiers().contains(ElementModifier.STATIC)) {
|
if (method.getModifiers().contains(ElementModifier.STATIC)) {
|
||||||
|
@ -808,9 +817,9 @@ public class Renderer implements RenderingManager {
|
||||||
longLibraryUsed |= statementRenderer.isLongLibraryUsed();
|
longLibraryUsed |= statementRenderer.isLongLibraryUsed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderFunctionDeclaration(String className, String name) throws IOException {
|
private void renderFunctionDeclaration(String name) throws IOException {
|
||||||
if (classScoped) {
|
if (classScoped) {
|
||||||
writer.appendClass(className).append(".").append(name).ws().append("=").ws();
|
writer.append(CONTAINER_OBJECT).append(".").append(name).ws().append("=").ws();
|
||||||
}
|
}
|
||||||
writer.append("function");
|
writer.append("function");
|
||||||
if (!classScoped) {
|
if (!classScoped) {
|
||||||
|
@ -1074,8 +1083,12 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String typeToClassString(ValueType type) {
|
public void typeToClassString(SourceWriter writer, ValueType type) {
|
||||||
return context.typeToClsString(type);
|
try {
|
||||||
|
context.typeToClsString(writer, type);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.javascript.rendering;
|
package org.teavm.backend.javascript.rendering;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
@ -27,6 +28,7 @@ import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
||||||
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.backend.javascript.spi.InjectedBy;
|
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||||
import org.teavm.backend.javascript.spi.Injector;
|
import org.teavm.backend.javascript.spi.Injector;
|
||||||
import org.teavm.common.ServiceRepository;
|
import org.teavm.common.ServiceRepository;
|
||||||
|
@ -156,73 +158,122 @@ public class RenderingContext {
|
||||||
return readonlyStringPool;
|
return readonlyStringPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String constantToString(Object cst) {
|
public void constantToString(SourceWriter writer, Object cst) throws IOException {
|
||||||
if (cst == null) {
|
if (cst == null) {
|
||||||
return "null";
|
writer.append("null");
|
||||||
}
|
}
|
||||||
if (cst instanceof ValueType) {
|
if (cst instanceof ValueType) {
|
||||||
ValueType type = (ValueType) cst;
|
ValueType type = (ValueType) cst;
|
||||||
return naming.getNameForFunction("$rt_cls") + "(" + typeToClsString(type) + ")";
|
writer.appendFunction("$rt_cls").append("(");
|
||||||
|
typeToClsString(writer, type);
|
||||||
|
writer.append(")");
|
||||||
} else if (cst instanceof String) {
|
} else if (cst instanceof String) {
|
||||||
String string = (String) cst;
|
String string = (String) cst;
|
||||||
int index = lookupString(string);
|
int index = lookupString(string);
|
||||||
return naming.getNameForFunction("$rt_s") + "(" + index + ")";
|
writer.appendFunction("$rt_s").append("(" + index + ")");
|
||||||
} else if (cst instanceof Long) {
|
} else if (cst instanceof Long) {
|
||||||
long value = (Long) cst;
|
long value = (Long) cst;
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
return "Long_ZERO";
|
writer.append("Long_ZERO");
|
||||||
} else if ((int) value == value) {
|
} else if ((int) value == value) {
|
||||||
return "Long_fromInt(" + value + ")";
|
writer.append("Long_fromInt(" + value + ")");
|
||||||
} else {
|
} else {
|
||||||
return "new Long(" + (value & 0xFFFFFFFFL) + ", " + (value >>> 32) + ")";
|
writer.append("new Long(" + (value & 0xFFFFFFFFL) + ", " + (value >>> 32) + ")");
|
||||||
}
|
}
|
||||||
} else if (cst instanceof Character) {
|
} else if (cst instanceof Character) {
|
||||||
return Integer.toString((Character) cst);
|
writer.append(Integer.toString((Character) cst));
|
||||||
} else if (cst instanceof Boolean) {
|
} else if (cst instanceof Boolean) {
|
||||||
return (Boolean) cst ? "1" : "0";
|
writer.append((Boolean) cst ? "1" : "0");
|
||||||
} else {
|
} else if (cst instanceof Integer) {
|
||||||
return cst.toString();
|
int value = (Integer) cst;
|
||||||
|
if (value < 0) {
|
||||||
|
writer.append("(");
|
||||||
|
writer.append(Integer.toString(value));
|
||||||
|
writer.append(")");
|
||||||
|
} else {
|
||||||
|
writer.append(Integer.toString(value));
|
||||||
|
}
|
||||||
|
} else if (cst instanceof Byte) {
|
||||||
|
int value = (Byte) cst;
|
||||||
|
if (value < 0) {
|
||||||
|
writer.append("(");
|
||||||
|
writer.append(Integer.toString(value));
|
||||||
|
writer.append(")");
|
||||||
|
} else {
|
||||||
|
writer.append(Integer.toString(value));
|
||||||
|
}
|
||||||
|
} else if (cst instanceof Short) {
|
||||||
|
int value = (Short) cst;
|
||||||
|
if (value < 0) {
|
||||||
|
writer.append("(");
|
||||||
|
writer.append(Integer.toString(value));
|
||||||
|
writer.append(")");
|
||||||
|
} else {
|
||||||
|
writer.append(Integer.toString(value));
|
||||||
|
}
|
||||||
|
} else if (cst instanceof Double) {
|
||||||
|
double value = (Double) cst;
|
||||||
|
if (value < 0) {
|
||||||
|
writer.append("(");
|
||||||
|
writer.append(Double.toString(value));
|
||||||
|
writer.append(")");
|
||||||
|
} else {
|
||||||
|
writer.append(Double.toString(value));
|
||||||
|
}
|
||||||
|
} else if (cst instanceof Float) {
|
||||||
|
float value = (Float) cst;
|
||||||
|
if (value < 0) {
|
||||||
|
writer.append("(");
|
||||||
|
writer.append(Float.toString(value));
|
||||||
|
writer.append(")");
|
||||||
|
} else {
|
||||||
|
writer.append(Float.toString(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String typeToClsString(ValueType type) {
|
public void typeToClsString(SourceWriter writer, ValueType type) throws IOException {
|
||||||
int arrayCount = 0;
|
int arrayCount = 0;
|
||||||
while (type instanceof ValueType.Array) {
|
while (type instanceof ValueType.Array) {
|
||||||
arrayCount++;
|
arrayCount++;
|
||||||
type = ((ValueType.Array) type).getItemType();
|
type = ((ValueType.Array) type).getItemType();
|
||||||
}
|
}
|
||||||
String value;
|
|
||||||
|
for (int i = 0; i < arrayCount; ++i) {
|
||||||
|
writer.append("$rt_arraycls(");
|
||||||
|
}
|
||||||
|
|
||||||
if (type instanceof ValueType.Object) {
|
if (type instanceof ValueType.Object) {
|
||||||
ValueType.Object objType = (ValueType.Object) type;
|
ValueType.Object objType = (ValueType.Object) type;
|
||||||
value = naming.getNameFor(objType.getClassName());
|
writer.appendClass(objType.getClassName());
|
||||||
} else if (type instanceof ValueType.Void) {
|
} else if (type instanceof ValueType.Void) {
|
||||||
value = "$rt_voidcls()";
|
writer.append("$rt_voidcls()");
|
||||||
} else if (type instanceof ValueType.Primitive) {
|
} else if (type instanceof ValueType.Primitive) {
|
||||||
ValueType.Primitive primitiveType = (ValueType.Primitive) type;
|
ValueType.Primitive primitiveType = (ValueType.Primitive) type;
|
||||||
switch (primitiveType.getKind()) {
|
switch (primitiveType.getKind()) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
value = "$rt_booleancls()";
|
writer.append("$rt_booleancls()");
|
||||||
break;
|
break;
|
||||||
case CHARACTER:
|
case CHARACTER:
|
||||||
value = "$rt_charcls()";
|
writer.append("$rt_charcls()");
|
||||||
break;
|
break;
|
||||||
case BYTE:
|
case BYTE:
|
||||||
value = "$rt_bytecls()";
|
writer.append("$rt_bytecls()");
|
||||||
break;
|
break;
|
||||||
case SHORT:
|
case SHORT:
|
||||||
value = "$rt_shortcls()";
|
writer.append("$rt_shortcls()");
|
||||||
break;
|
break;
|
||||||
case INTEGER:
|
case INTEGER:
|
||||||
value = "$rt_intcls()";
|
writer.append("$rt_intcls()");
|
||||||
break;
|
break;
|
||||||
case LONG:
|
case LONG:
|
||||||
value = "$rt_longcls()";
|
writer.append("$rt_longcls()");
|
||||||
break;
|
break;
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
value = "$rt_floatcls()";
|
writer.append("$rt_floatcls()");
|
||||||
break;
|
break;
|
||||||
case DOUBLE:
|
case DOUBLE:
|
||||||
value = "$rt_doublecls()";
|
writer.append("$rt_doublecls()");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("The type is not renderable");
|
throw new IllegalArgumentException("The type is not renderable");
|
||||||
|
@ -232,9 +283,8 @@ public class RenderingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < arrayCount; ++i) {
|
for (int i = 0; i < arrayCount; ++i) {
|
||||||
value = "$rt_arraycls(" + value + ")";
|
writer.append(")");
|
||||||
}
|
}
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String pointerName() {
|
public String pointerName() {
|
||||||
|
|
|
@ -1006,11 +1006,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
if (expr.getLocation() != null) {
|
if (expr.getLocation() != null) {
|
||||||
pushLocation(expr.getLocation());
|
pushLocation(expr.getLocation());
|
||||||
}
|
}
|
||||||
String str = context.constantToString(expr.getValue());
|
context.constantToString(writer, expr.getValue());
|
||||||
if (str.startsWith("-")) {
|
|
||||||
writer.append(' ');
|
|
||||||
}
|
|
||||||
writer.append(str);
|
|
||||||
if (expr.getLocation() != null) {
|
if (expr.getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
@ -1198,7 +1194,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
precedence = Precedence.FUNCTION_CALL;
|
precedence = Precedence.FUNCTION_CALL;
|
||||||
|
|
||||||
writer.append("new ").append(naming.getNameFor(expr.getConstructedClass()));
|
writer.append("new ").appendClass(expr.getConstructedClass());
|
||||||
if (outerPrecedence.ordinal() > Precedence.FUNCTION_CALL.ordinal()) {
|
if (outerPrecedence.ordinal() > Precedence.FUNCTION_CALL.ordinal()) {
|
||||||
writer.append(')');
|
writer.append(')');
|
||||||
}
|
}
|
||||||
|
@ -1270,8 +1266,9 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writer.appendFunction("$rt_createArray").append("(").append(context.typeToClsString(expr.getType()))
|
writer.appendFunction("$rt_createArray").append("(");
|
||||||
.append(",").ws();
|
context.typeToClsString(writer, expr.getType());
|
||||||
|
writer.append(",").ws();
|
||||||
precedence = Precedence.min();
|
precedence = Precedence.min();
|
||||||
expr.getLength().acceptVisitor(this);
|
expr.getLength().acceptVisitor(this);
|
||||||
writer.append(")");
|
writer.append(")");
|
||||||
|
@ -1322,8 +1319,9 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writer.append("$rt_createMultiArray(").append(context.typeToClsString(expr.getType()))
|
writer.append("$rt_createMultiArray(");
|
||||||
.append(",").ws();
|
context.typeToClsString(writer, expr.getType());
|
||||||
|
writer.append(",").ws();
|
||||||
}
|
}
|
||||||
writer.append("[");
|
writer.append("[");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
|
@ -1375,7 +1373,9 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
writer.appendFunction("$rt_isInstance").append("(");
|
writer.appendFunction("$rt_isInstance").append("(");
|
||||||
precedence = Precedence.min();
|
precedence = Precedence.min();
|
||||||
expr.getExpr().acceptVisitor(this);
|
expr.getExpr().acceptVisitor(this);
|
||||||
writer.append(",").ws().append(context.typeToClsString(expr.getType())).append(")");
|
writer.append(",").ws();
|
||||||
|
context.typeToClsString(writer, expr.getType());
|
||||||
|
writer.append(")");
|
||||||
if (expr.getLocation() != null) {
|
if (expr.getLocation() != null) {
|
||||||
popLocation();
|
popLocation();
|
||||||
}
|
}
|
||||||
|
@ -1554,16 +1554,16 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeType(ValueType type) throws IOException {
|
public void writeType(ValueType type) throws IOException {
|
||||||
writer.append(context.typeToClsString(type));
|
context.typeToClsString(writer, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeExpr(Expr expr) throws IOException {
|
public void writeExpr(Expr expr) {
|
||||||
writeExpr(expr, Precedence.GROUPING);
|
writeExpr(expr, Precedence.GROUPING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeExpr(Expr expr, Precedence precedence) throws IOException {
|
public void writeExpr(Expr expr, Precedence precedence) {
|
||||||
StatementRenderer.this.precedence = precedence;
|
StatementRenderer.this.precedence = precedence;
|
||||||
expr.acceptVisitor(StatementRenderer.this);
|
expr.acceptVisitor(StatementRenderer.this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package org.teavm.backend.javascript.spi;
|
package org.teavm.backend.javascript.spi;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.common.ServiceRepository;
|
import org.teavm.common.ServiceRepository;
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
@ -42,7 +43,7 @@ public interface GeneratorContext extends ServiceRepository {
|
||||||
|
|
||||||
Diagnostics getDiagnostics();
|
Diagnostics getDiagnostics();
|
||||||
|
|
||||||
String typeToClassString(ValueType type);
|
void typeToClassString(SourceWriter writer, ValueType type);
|
||||||
|
|
||||||
void useLongLibrary();
|
void useLongLibrary();
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,9 +39,9 @@ public interface InjectorContext extends ServiceRepository {
|
||||||
|
|
||||||
void writeType(ValueType type) throws IOException;
|
void writeType(ValueType type) throws IOException;
|
||||||
|
|
||||||
void writeExpr(Expr expr) throws IOException;
|
void writeExpr(Expr expr);
|
||||||
|
|
||||||
void writeExpr(Expr expr, Precedence precedence) throws IOException;
|
void writeExpr(Expr expr, Precedence precedence);
|
||||||
|
|
||||||
Precedence getPrecedence();
|
Precedence getPrecedence();
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
protected void callMethod(String ident, String fqn, String method, String params) {
|
||||||
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
||||||
MethodReference methodRef = new MethodReference(fqn, desc);
|
MethodReference methodRef = new MethodReference(fqn, desc);
|
||||||
|
|
||||||
|
@ -170,8 +170,14 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener {
|
||||||
} else {
|
} else {
|
||||||
allClassesNode.addConsumer(new VirtualCallbackConsumer(agent, methodRef));
|
allClassesNode.addConsumer(new VirtualCallbackConsumer(agent, methodRef));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return "";
|
@Override
|
||||||
|
protected void append(String text) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void reportDiagnostic(String text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,13 @@ package org.teavm.html4j;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import net.java.html.js.JavaScriptBody;
|
import net.java.html.js.JavaScriptBody;
|
||||||
import org.teavm.backend.javascript.codegen.NamingStrategy;
|
|
||||||
import org.teavm.backend.javascript.codegen.SourceWriter;
|
import org.teavm.backend.javascript.codegen.SourceWriter;
|
||||||
import org.teavm.backend.javascript.spi.Generator;
|
import org.teavm.backend.javascript.spi.Generator;
|
||||||
import org.teavm.backend.javascript.spi.GeneratorContext;
|
import org.teavm.backend.javascript.spi.GeneratorContext;
|
||||||
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.model.AnnotationReader;
|
import org.teavm.model.AnnotationReader;
|
||||||
import org.teavm.model.AnnotationValue;
|
import org.teavm.model.AnnotationValue;
|
||||||
|
import org.teavm.model.CallLocation;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.ElementModifier;
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
|
@ -40,11 +41,6 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
String body = annot.getValue("body").getString();
|
String body = annot.getValue("body").getString();
|
||||||
List<AnnotationValue> args = annot.getValue("args").getList();
|
List<AnnotationValue> args = annot.getValue("args").getList();
|
||||||
AnnotationValue javacall = annot.getValue("javacall");
|
AnnotationValue javacall = annot.getValue("javacall");
|
||||||
if (javacall != null && javacall.getBoolean()) {
|
|
||||||
GeneratorJsCallback callbackGen = new GeneratorJsCallback(context, context.getClassSource(),
|
|
||||||
writer.getNaming());
|
|
||||||
body = callbackGen.parse(body);
|
|
||||||
}
|
|
||||||
writer.append("var result = (function(");
|
writer.append("var result = (function(");
|
||||||
for (int i = 0; i < args.size(); ++i) {
|
for (int i = 0; i < args.size(); ++i) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
|
@ -53,7 +49,14 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
writer.append(args.get(i).getString());
|
writer.append(args.get(i).getString());
|
||||||
}
|
}
|
||||||
writer.append(")").ws().append("{").indent().softNewLine();
|
writer.append(")").ws().append("{").indent().softNewLine();
|
||||||
writer.append(body).softNewLine();
|
if (javacall != null && javacall.getBoolean()) {
|
||||||
|
GeneratorJsCallback callbackGen = new GeneratorJsCallback(writer, context, context.getClassSource(),
|
||||||
|
context.getDiagnostics(), methodRef);
|
||||||
|
callbackGen.parse(body);
|
||||||
|
} else {
|
||||||
|
writer.append(body);
|
||||||
|
}
|
||||||
|
writer.softNewLine();
|
||||||
writer.outdent().append("}).call(").append(!method.hasModifier(ElementModifier.STATIC)
|
writer.outdent().append("}).call(").append(!method.hasModifier(ElementModifier.STATIC)
|
||||||
? context.getParameterName(0) : "null");
|
? context.getParameterName(0) : "null");
|
||||||
for (int i = 0; i < args.size(); ++i) {
|
for (int i = 0; i < args.size(); ++i) {
|
||||||
|
@ -71,65 +74,88 @@ public class JavaScriptBodyGenerator implements Generator {
|
||||||
writer.append("(").append(param).append(")");
|
writer.append("(").append(param).append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void unwrapValue(GeneratorContext context, SourceWriter writer, ValueType type)
|
private void unwrapValue(GeneratorContext context, SourceWriter writer, ValueType type) throws IOException {
|
||||||
throws IOException {
|
|
||||||
writer.appendMethodBody(JavaScriptConvGenerator.fromJsMethod);
|
writer.appendMethodBody(JavaScriptConvGenerator.fromJsMethod);
|
||||||
writer.append("(").append("result").append(",").ws().append(context.typeToClassString(type))
|
writer.append("(").append("result").append(",").ws();
|
||||||
.append(")");
|
context.typeToClassString(writer, type);
|
||||||
|
writer.append(")");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class GeneratorJsCallback extends JsCallback {
|
private static class GeneratorJsCallback extends JsCallback {
|
||||||
|
private SourceWriter writer;
|
||||||
private GeneratorContext context;
|
private GeneratorContext context;
|
||||||
private ClassReaderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
private NamingStrategy naming;
|
private Diagnostics diagnostics;
|
||||||
|
private MethodReference methodReference;
|
||||||
|
|
||||||
GeneratorJsCallback(GeneratorContext context, ClassReaderSource classSource, NamingStrategy naming) {
|
GeneratorJsCallback(SourceWriter writer, GeneratorContext context, ClassReaderSource classSource,
|
||||||
|
Diagnostics diagnostics, MethodReference methodReference) {
|
||||||
|
this.writer = writer;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.naming = naming;
|
this.diagnostics = diagnostics;
|
||||||
|
this.methodReference = methodReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CharSequence callMethod(String ident, String fqn, String method, String params) {
|
protected void callMethod(String ident, String fqn, String method, String params) {
|
||||||
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
try {
|
||||||
MethodReader reader = JavaScriptBodyDependency.findMethod(classSource, fqn, desc);
|
MethodDescriptor desc = MethodDescriptor.parse(method + params + "V");
|
||||||
if (reader == null) {
|
MethodReader reader = JavaScriptBodyDependency.findMethod(classSource, fqn, desc);
|
||||||
return "";
|
if (reader == null) {
|
||||||
}
|
return;
|
||||||
desc = reader.getDescriptor();
|
}
|
||||||
|
desc = reader.getDescriptor();
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
writer.append("(function(");
|
||||||
sb.append("(function(");
|
if (ident != null) {
|
||||||
if (ident != null) {
|
writer.append("$this");
|
||||||
sb.append("$this");
|
|
||||||
}
|
|
||||||
for (int i = 0; i < desc.parameterCount(); ++i) {
|
|
||||||
if (ident != null || i > 0) {
|
|
||||||
sb.append(", ");
|
|
||||||
}
|
}
|
||||||
sb.append("p").append(i);
|
for (int i = 0; i < desc.parameterCount(); ++i) {
|
||||||
}
|
if (ident != null || i > 0) {
|
||||||
sb.append(") { return ").append(naming.getFullNameFor(JavaScriptConvGenerator.toJsMethod)).append("(");
|
writer.append(",").ws();
|
||||||
if (ident == null) {
|
}
|
||||||
sb.append(naming.getFullNameFor(reader.getReference()));
|
writer.append("p").append(i);
|
||||||
} else {
|
|
||||||
sb.append("$this.").append(naming.getNameFor(desc));
|
|
||||||
}
|
|
||||||
sb.append("(");
|
|
||||||
for (int i = 0; i < desc.parameterCount(); ++i) {
|
|
||||||
if (i > 0) {
|
|
||||||
sb.append(", ");
|
|
||||||
}
|
}
|
||||||
ValueType paramType = simplifyParamType(desc.parameterType(i));
|
writer.append(")").ws().append("{").ws().append("return ")
|
||||||
sb.append(naming.getFullNameFor(JavaScriptConvGenerator.fromJsMethod)).append("(p").append(i)
|
.appendMethodBody(JavaScriptConvGenerator.toJsMethod).append("(");
|
||||||
.append(", ")
|
if (ident == null) {
|
||||||
.append(context.typeToClassString(paramType)).append(")");
|
writer.appendMethodBody(reader.getReference());
|
||||||
|
} else {
|
||||||
|
writer.append("$this.").appendMethod(desc);
|
||||||
|
}
|
||||||
|
writer.append("(");
|
||||||
|
for (int i = 0; i < desc.parameterCount(); ++i) {
|
||||||
|
if (i > 0) {
|
||||||
|
writer.append(",").ws();
|
||||||
|
}
|
||||||
|
ValueType paramType = simplifyParamType(desc.parameterType(i));
|
||||||
|
writer.appendMethodBody(JavaScriptConvGenerator.fromJsMethod).append("(p").append(i)
|
||||||
|
.append(",").ws();
|
||||||
|
context.typeToClassString(writer, paramType);
|
||||||
|
writer.append(")");
|
||||||
|
}
|
||||||
|
writer.append("));").ws().append("})(");
|
||||||
|
if (ident != null) {
|
||||||
|
writer.append(ident);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
sb.append(")); })(");
|
}
|
||||||
if (ident != null) {
|
|
||||||
sb.append(ident);
|
@Override
|
||||||
|
protected void append(String text) {
|
||||||
|
try {
|
||||||
|
writer.append(text);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
return sb.toString();
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void reportDiagnostic(String text) {
|
||||||
|
diagnostics.error(new CallLocation(methodReference), text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ValueType simplifyParamType(ValueType type) {
|
private ValueType simplifyParamType(ValueType type) {
|
||||||
|
|
|
@ -13,153 +13,80 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
/**
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
||||||
*
|
|
||||||
* Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
|
|
||||||
*
|
|
||||||
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
|
|
||||||
* Other names may be trademarks of their respective owners.
|
|
||||||
*
|
|
||||||
* The contents of this file are subject to the terms of either the GNU
|
|
||||||
* General Public License Version 2 only ("GPL") or the Common
|
|
||||||
* Development and Distribution License("CDDL") (collectively, the
|
|
||||||
* "License"). You may not use this file except in compliance with the
|
|
||||||
* License. You can obtain a copy of the License at
|
|
||||||
* http://www.netbeans.org/cddl-gplv2.html
|
|
||||||
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
|
||||||
* specific language governing permissions and limitations under the
|
|
||||||
* License. When distributing the software, include this License Header
|
|
||||||
* Notice in each file and include the License file at
|
|
||||||
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
|
|
||||||
* particular file as subject to the "Classpath" exception as provided
|
|
||||||
* by Oracle in the GPL Version 2 section of the License file that
|
|
||||||
* accompanied this code. If applicable, add the following below the
|
|
||||||
* License Header, with the fields enclosed by brackets [] replaced by
|
|
||||||
* your own identifying information:
|
|
||||||
* "Portions Copyrighted [year] [name of copyright owner]"
|
|
||||||
*
|
|
||||||
* Contributor(s):
|
|
||||||
*
|
|
||||||
* The Original Software is NetBeans. The Initial Developer of the Original
|
|
||||||
* Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* If you wish your version of this file to be governed by only the CDDL
|
|
||||||
* or only the GPL Version 2, indicate your decision by adding
|
|
||||||
* "[Contributor] elects to include this software in this distribution
|
|
||||||
* under the [CDDL or GPL Version 2] license." If you do not indicate a
|
|
||||||
* single choice of license, a recipient has the option to distribute
|
|
||||||
* your version of this file under either the CDDL, the GPL Version 2 or
|
|
||||||
* to extend the choice of license to its licensees as provided above.
|
|
||||||
* However, if you add GPL Version 2 code and therefore, elected the GPL
|
|
||||||
* Version 2 license, then the option applies only if the new code is
|
|
||||||
* made subject to such option by the copyright holder.
|
|
||||||
*/
|
|
||||||
package org.teavm.html4j;
|
package org.teavm.html4j;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Jaroslav Tulach <jtulach@netbeans.org>
|
|
||||||
*/
|
|
||||||
abstract class JsCallback {
|
abstract class JsCallback {
|
||||||
final String parse(String body) {
|
final void parse(String body) {
|
||||||
StringBuilder sb = new StringBuilder();
|
int pos = 0;
|
||||||
int pos = 0;
|
while (true) {
|
||||||
for (;;) {
|
int next = body.indexOf('@', pos);
|
||||||
int next = body.indexOf(".@", pos);
|
if (next < 0) {
|
||||||
if (next == -1) {
|
append(body.substring(pos));
|
||||||
sb.append(body.substring(pos));
|
break;
|
||||||
body = sb.toString();
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
int ident = next;
|
|
||||||
while (ident > 0) {
|
|
||||||
if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
|
|
||||||
ident++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String refId = body.substring(ident, next);
|
|
||||||
|
|
||||||
sb.append(body.substring(pos, ident));
|
String refId = null;
|
||||||
|
if (next > 0 && body.charAt(next - 1) == '.') {
|
||||||
|
int ident = next - 1;
|
||||||
|
while (ident > 0) {
|
||||||
|
if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
|
||||||
|
ident++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refId = body.substring(ident, next - 1);
|
||||||
|
append(body.substring(pos, ident));
|
||||||
|
} else {
|
||||||
|
append(body.substring(pos, next));
|
||||||
|
}
|
||||||
|
|
||||||
int sigBeg = body.indexOf('(', next);
|
int colon4 = body.indexOf("::", next);
|
||||||
int sigEnd = body.indexOf(')', sigBeg);
|
int sigBeg = body.indexOf('(', colon4 > 0 ? colon4 : next);
|
||||||
int colon4 = body.indexOf("::", next);
|
int sigEnd = body.indexOf(')', sigBeg > 0 ? sigBeg : next);
|
||||||
if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
|
|
||||||
throw new IllegalStateException("Wrong format of instance callback. Should be: "
|
|
||||||
+ "'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" + body);
|
|
||||||
}
|
|
||||||
String fqn = body.substring(next + 2, colon4);
|
|
||||||
String method = body.substring(colon4 + 2, sigBeg);
|
|
||||||
String params = body.substring(sigBeg, sigEnd + 1);
|
|
||||||
|
|
||||||
int paramBeg = body.indexOf('(', sigEnd + 1);
|
if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
|
||||||
if (paramBeg == -1) {
|
reportDiagnostic("Wrong format of callback. Should be: "
|
||||||
throw new IllegalStateException("Wrong format of instance callback. "
|
+ "'@pkg.Class::method(Ljava/lang/Object;)(param)'" + body);
|
||||||
+ "Should be: 'inst.@pkg.Class::method(Ljava/lang/Object;)(param)':\n" + body);
|
append(body.substring(pos, next + 1));
|
||||||
}
|
pos = next + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sb.append(callMethod(refId, fqn, method, params));
|
int paramBeg = body.indexOf('(', sigEnd + 1);
|
||||||
if (body.charAt(paramBeg + 1) != ')') {
|
if (paramBeg < 0 || !isWhitespaces(body, sigEnd + 1, paramBeg)) {
|
||||||
sb.append(",");
|
reportDiagnostic("Wrong format of callback. Should be: "
|
||||||
}
|
+ "'@pkg.Class::method(Ljava/lang/Object;)(param)'" + body);
|
||||||
pos = paramBeg + 1;
|
append(body.substring(pos, next + 1));
|
||||||
}
|
pos = next + 1;
|
||||||
pos = 0;
|
continue;
|
||||||
sb = null;
|
}
|
||||||
for (;;) {
|
|
||||||
int next = body.indexOf("@", pos);
|
|
||||||
if (next == -1) {
|
|
||||||
if (sb == null) {
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
sb.append(body.substring(pos));
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
if (sb == null) {
|
|
||||||
sb = new StringBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.append(body.substring(pos, next));
|
String fqn = body.substring(next + 1, colon4);
|
||||||
|
String method = body.substring(colon4 + 2, sigBeg);
|
||||||
|
String params = body.substring(sigBeg, sigEnd + 1);
|
||||||
|
|
||||||
int sigBeg = body.indexOf('(', next);
|
callMethod(refId, fqn, method, params);
|
||||||
int sigEnd = body.indexOf(')', sigBeg);
|
|
||||||
int colon4 = body.indexOf("::", next);
|
|
||||||
if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
|
|
||||||
throw new IllegalStateException("Wrong format of static callback. Should be: "
|
|
||||||
+ "'@pkg.Class::staticMethod(Ljava/lang/Object;)(param)':\n" + body);
|
|
||||||
}
|
|
||||||
String fqn = body.substring(next + 1, colon4);
|
|
||||||
String method = body.substring(colon4 + 2, sigBeg);
|
|
||||||
String params = body.substring(sigBeg, sigEnd + 1);
|
|
||||||
|
|
||||||
int paramBeg = body.indexOf('(', sigEnd + 1);
|
if (refId != null && body.charAt(paramBeg + 1) != ')') {
|
||||||
|
append(",");
|
||||||
|
}
|
||||||
|
|
||||||
sb.append(callMethod(null, fqn, method, params));
|
pos = paramBeg + 1;
|
||||||
pos = paramBeg + 1;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract CharSequence callMethod(
|
protected abstract void append(String text);
|
||||||
String ident, String fqn, String method, String params
|
|
||||||
);
|
|
||||||
|
|
||||||
static String mangle(String fqn, String method, String params) {
|
protected abstract void callMethod(String ident, String fqn, String method, String params);
|
||||||
if (params.startsWith("(")) {
|
|
||||||
params = params.substring(1);
|
|
||||||
}
|
|
||||||
if (params.endsWith(")")) {
|
|
||||||
params = params.substring(0, params.length() - 1);
|
|
||||||
}
|
|
||||||
return
|
|
||||||
replace(fqn) + "$" + replace(method) + "$" + replace(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String replace(String orig) {
|
protected abstract void reportDiagnostic(String text);
|
||||||
return orig.replace("_", "_1").
|
|
||||||
replace(";", "_2").
|
private static boolean isWhitespaces(String text, int start, int end) {
|
||||||
replace("[", "_3").
|
while (start < end) {
|
||||||
replace('.', '_').replace('/', '_');
|
if (!Character.isWhitespace(text.charAt(start++))) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user