Adds integer conversion

This commit is contained in:
konsoletyper 2014-02-17 17:05:17 +04:00
parent ae2ca37ee0
commit 169ecb18c8
6 changed files with 75 additions and 72 deletions

View File

@ -43,6 +43,10 @@ $rt_createArray = function(cls, sz) {
} }
return arr; return arr;
} }
$rt_wrapArray = function(cls, data) {
var arr = new ($rt_arraycls(cls))(data);
return arr;
}
$rt_createUnfilledArray = function(cls, sz) { $rt_createUnfilledArray = function(cls, sz) {
return new ($rt_arraycls(cls))(new Array(sz)); return new ($rt_arraycls(cls))(new Array(sz));
} }

View File

@ -15,7 +15,6 @@
*/ */
package org.teavm.html4j; package org.teavm.html4j;
import org.teavm.dependency.PluggableDependency;
import org.teavm.javascript.ni.GeneratedBy; import org.teavm.javascript.ni.GeneratedBy;
/** /**
@ -27,6 +26,8 @@ public final class JavaScriptBodyConverter {
} }
@GeneratedBy(JavaScriptBodyConverterGenerator.class) @GeneratedBy(JavaScriptBodyConverterGenerator.class)
@PluggableDependency(JavaScriptBodyConverterGenerator.class)
public static native Object toJavaScript(Object obj); public static native Object toJavaScript(Object obj);
@GeneratedBy(JavaScriptBodyConverterGenerator.class)
public static native Object fromJavaScript(Object obj);
} }

View File

@ -17,10 +17,6 @@ package org.teavm.html4j;
import java.io.IOException; import java.io.IOException;
import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriter;
import org.teavm.dependency.DependencyChecker;
import org.teavm.dependency.DependencyConsumer;
import org.teavm.dependency.DependencyPlugin;
import org.teavm.dependency.MethodGraph;
import org.teavm.javascript.ni.Generator; import org.teavm.javascript.ni.Generator;
import org.teavm.javascript.ni.GeneratorContext; import org.teavm.javascript.ni.GeneratorContext;
import org.teavm.model.*; import org.teavm.model.*;
@ -29,29 +25,15 @@ import org.teavm.model.*;
* *
* @author Alexey Andreev <konsoletyper@gmail.com> * @author Alexey Andreev <konsoletyper@gmail.com>
*/ */
public class JavaScriptBodyConverterGenerator implements Generator, DependencyPlugin { public class JavaScriptBodyConverterGenerator implements Generator {
private static final MethodReference intValueMethod = new MethodReference("java.lang.Integer", private static final String convCls = JavaScriptBodyConverter.class.getName();
static final MethodReference intValueMethod = new MethodReference("java.lang.Integer",
new MethodDescriptor("intValue", ValueType.INTEGER)); new MethodDescriptor("intValue", ValueType.INTEGER));
private static final ValueType objType = ValueType.object("java.lang.Object");
@Override static final MethodReference toJsMethod = new MethodReference(convCls, new MethodDescriptor(
public void methodAchieved(DependencyChecker checker, MethodReference method) { "toJavaScript", objType, objType));
switch (method.getName()) { static final MethodReference fromJsMethod = new MethodReference(convCls, new MethodDescriptor(
case "toJavaScript": "fromJavaScript", objType, objType));
achieveToJavaScript(checker, method);
break;
}
}
private void achieveToJavaScript(final DependencyChecker checker, MethodReference method) {
MethodGraph graph = checker.attachMethodGraph(method);
graph.getVariable(1).addConsumer(new DependencyConsumer() {
@Override public void consume(String type) {
if (type.equals("java.lang.Integer")) {
checker.attachMethodGraph(intValueMethod);
}
}
});
}
@Override @Override
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
@ -59,32 +41,52 @@ public class JavaScriptBodyConverterGenerator implements Generator, DependencyPl
case "toJavaScript": case "toJavaScript":
generateToJavaScript(context, writer); generateToJavaScript(context, writer);
break; break;
case "fromJavaScript":
generateFromJavaScript(context, writer);
break;
} }
} }
private void generateToJavaScript(GeneratorContext context, SourceWriter writer) throws IOException { private void generateToJavaScript(GeneratorContext context, SourceWriter writer) throws IOException {
ClassReaderSource classSource = context.getClassSource();
String obj = context.getParameterName(1); String obj = context.getParameterName(1);
writer.append("if").ws().append("(").append(obj).ws().append("===").ws().append("null)").ws().append("{") writer.append("if (" + obj + " === null) {").softNewLine().indent();
writer.append("return null;").softNewLine();
writer.outdent().append("} else if (" + obj + ".constructor.$meta.item) {").indent().softNewLine();
writer.append("var arr = new Array(" + obj + ".data.length);").softNewLine();
writer.append("for (var i = 0; i < arr.length; ++i) {").indent().softNewLine();
writer.append("arr[i] = ").appendMethodBody(toJsMethod).append("(" + obj + ".data[i]);").softNewLine();
writer.outdent().append("}").softNewLine();
writer.append("return arr;").softNewLine();
writer.outdent().append("}");
writer.append(" else if (" + obj + ".constructor === ").appendClass("java.lang.String")
.append(") {").indent().softNewLine();
generateStringToJavaScript(context, writer);
writer.outdent().append("} else if (" + obj + ".constructor === ").appendClass("java.lang.Integer")
.append(") {").indent().softNewLine();
writer.append("return ").appendMethodBody(intValueMethod).append("(" + obj + ");").softNewLine();
writer.outdent().append("}");
writer.append(" else {").indent().softNewLine();
writer.append("return " + obj + ";").softNewLine();
writer.outdent().append("}").softNewLine();
}
private void generateFromJavaScript(GeneratorContext context, SourceWriter writer) throws IOException {
String obj = context.getParameterName(1);
writer.append("if (" + obj +" === null || " + obj + " === undefined)").ws().append("{")
.softNewLine().indent(); .softNewLine().indent();
writer.append("return null;").softNewLine(); writer.append("return null;").softNewLine();
writer.outdent().append("}").ws().append("else if").ws().append('(').append(obj) writer.outdent().append("} else if (" + obj + " instanceof Array) {").indent().softNewLine();
.append(".constructor.$meta.item)").ws().append("{").indent().softNewLine(); writer.append("var arr = $rt_createArray($rt_objcls(), " + obj + ".length);").softNewLine();
writer.append("return ").append(obj).append(".data;").softNewLine(); writer.append("for (var i = 0; i < arr.data.length; ++i) {").indent().softNewLine();
writer.append("arr.data[i] = ").appendMethodBody(fromJsMethod).append("(" + obj + "[i]);")
.softNewLine();
writer.outdent().append("}").softNewLine();
writer.append("return arr;").softNewLine();
writer.outdent().append("}"); writer.outdent().append("}");
if (classSource.get("java.lang.String") != null) { writer.append(" else if (" + obj + ".constructor === ").appendClass("java.lang.String")
writer.ws().append("else if").ws().append("(").append(obj).append(".constructor").ws().append("===").ws() .append(") {").indent().softNewLine();
.appendClass("java.lang.String").append(")").ws().append("{").indent().softNewLine(); writer.append("return $rt_str(" + obj + ");").softNewLine();
generateStringToJavaScript(context, writer);
writer.outdent().append("}"); writer.outdent().append("}");
}
if (classSource.get("java.lang.Integer") != null) {
writer.ws().append("else if").ws().append("(").append(obj).append(".constructor").ws().append("===").ws()
.appendClass("java.lang.Integer").append(")").ws().append("{").indent().softNewLine();
writer.append("return ").appendMethodBody(intValueMethod).append("(").append(obj)
.append(");").softNewLine();
writer.outdent().append("}");
}
writer.ws().append("else").ws().append("{").indent().softNewLine(); writer.ws().append("else").ws().append("{").indent().softNewLine();
writer.append("return ").append(obj).append(";").softNewLine(); writer.append("return ").append(obj).append(";").softNewLine();
writer.outdent().append("}").softNewLine(); writer.outdent().append("}").softNewLine();

View File

@ -30,8 +30,6 @@ public class JavaScriptBodyDependency implements DependencyListener {
public void started(DependencyChecker dependencyChecker) { public void started(DependencyChecker dependencyChecker) {
allClassesNode = dependencyChecker.createNode(); allClassesNode = dependencyChecker.createNode();
allClassesNode.setTag("JavaScriptBody:global"); allClassesNode.setTag("JavaScriptBody:global");
allClassesNode.getArrayItem().addConsumer(new OneDirectionalConnection(allClassesNode));
allClassesNode.getArrayItem().getArrayItem().addConsumer(new OneDirectionalConnection(allClassesNode));
} }
private static class OneDirectionalConnection implements DependencyConsumer { private static class OneDirectionalConnection implements DependencyConsumer {
@ -55,6 +53,7 @@ public class JavaScriptBodyDependency implements DependencyListener {
MethodHolder method = cls.getMethod(methodRef.getDescriptor()); MethodHolder method = cls.getMethod(methodRef.getDescriptor());
AnnotationReader annot = method.getAnnotations().get(JavaScriptBody.class.getName()); AnnotationReader annot = method.getAnnotations().get(JavaScriptBody.class.getName());
if (annot != null) { if (annot != null) {
includeDefaultDependencies(dependencyChecker);
AnnotationValue javacall = annot.getValue("javacall"); AnnotationValue javacall = annot.getValue("javacall");
MethodGraph graph = dependencyChecker.attachMethodGraph(methodRef); MethodGraph graph = dependencyChecker.attachMethodGraph(methodRef);
if (graph.getResult() != null) { if (graph.getResult() != null) {
@ -73,17 +72,13 @@ public class JavaScriptBodyDependency implements DependencyListener {
String body = annot.getValue("body").getString(); String body = annot.getValue("body").getString();
new GeneratorJsCallback(dependencyChecker.getClassSource(), dependencyChecker).parse(body); new GeneratorJsCallback(dependencyChecker.getClassSource(), dependencyChecker).parse(body);
} }
for (int i = 0; i < methodRef.parameterCount(); ++i) {
ValueType type = methodRef.getDescriptor().parameterType(i);
if (type.isObject("java.lang.Object")) {
MethodGraph convGraph = dependencyChecker.attachMethodGraph(new MethodReference(
JavaScriptBodyConverter.class.getName(),
new MethodDescriptor("toJavaScript", ValueType.object("java.lang.Object"),
ValueType.object("java.lang.Object"))));
graph.getVariable(i + 1).connect(convGraph.getVariable(i + 1));
}
} }
} }
private void includeDefaultDependencies(DependencyChecker dependencyChecker) {
dependencyChecker.attachMethodGraph(JavaScriptBodyConverterGenerator.fromJsMethod);
dependencyChecker.attachMethodGraph(JavaScriptBodyConverterGenerator.toJsMethod);
dependencyChecker.attachMethodGraph(JavaScriptBodyConverterGenerator.intValueMethod);
} }
@Override @Override

View File

@ -41,7 +41,7 @@ public class JavaScriptBodyGenerator implements Generator {
GeneratorJsCallback callbackGen = new GeneratorJsCallback(context.getClassSource(), writer.getNaming()); GeneratorJsCallback callbackGen = new GeneratorJsCallback(context.getClassSource(), writer.getNaming());
body = callbackGen.parse(body); body = callbackGen.parse(body);
} }
writer.append("return (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) {
writer.append(",").ws(); writer.append(",").ws();
@ -55,14 +55,24 @@ public class JavaScriptBodyGenerator implements Generator {
writer.append(",").ws(); writer.append(",").ws();
wrapParameter(writer, methodRef.getDescriptor().parameterType(i), context.getParameterName(i + 1)); wrapParameter(writer, methodRef.getDescriptor().parameterType(i), context.getParameterName(i + 1));
} }
writer.append(");").softNewLine(); writer.append(")").softNewLine();
writer.append("return ");
unwrapValue(writer, method.getResultType(), "result");
writer.append(";").softNewLine();
} }
private void wrapParameter(SourceWriter writer, ValueType type, String param) throws IOException { private void wrapParameter(SourceWriter writer, ValueType type, String param) throws IOException {
if (type.isObject("java.lang.Object")) { if (type.isObject("java.lang.Object")) {
writer.appendMethodBody(new MethodReference(JavaScriptBodyConverter.class.getName(), writer.appendMethodBody(JavaScriptBodyConverterGenerator.toJsMethod);
new MethodDescriptor("toJavaScript", ValueType.object("java.lang.Object"), writer.append("(").append(param).append(")");
ValueType.object("java.lang.Object")))); } else {
writer.append(param);
}
}
private void unwrapValue(SourceWriter writer, ValueType type, String param) throws IOException {
if (type.isObject("java.lang.Object")) {
writer.appendMethodBody(JavaScriptBodyConverterGenerator.fromJsMethod);
writer.append("(").append(param).append(")"); writer.append("(").append(param).append(")");
} else { } else {
writer.append(param); writer.append(param);

View File

@ -49,15 +49,6 @@ public class JavaScriptBodyTests {
assertEquals(23, array[0].foo()); assertEquals(23, array[0].foo());
} }
@Test
public void dependencyPropagatedBackThroughArray() {
A[] first = new A[1];
storeObject(first);
Object[] second = (Object[])retrieveObject();
second[0] = new AImpl();
assertEquals(23, first[0].foo());
}
@Test @Test
public void valuePropagatedToCallback() { public void valuePropagatedToCallback() {
A a = new AImpl(); A a = new AImpl();