diff --git a/teavm-core/src/main/java/org/teavm/dependency/MethodDependency.java b/teavm-core/src/main/java/org/teavm/dependency/MethodDependency.java index cb1cce5b7..4b1b05931 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/MethodDependency.java +++ b/teavm-core/src/main/java/org/teavm/dependency/MethodDependency.java @@ -103,6 +103,19 @@ public class MethodDependency implements MethodDependencyInfo { return used; } + public MethodDependency propagate(int parameterIndex, Class type) { + return propagate(parameterIndex, dependencyChecker.getType(type.getName())); + } + + public MethodDependency propagate(int parameterIndex, String type) { + return propagate(parameterIndex, dependencyChecker.getType(type)); + } + + public MethodDependency propagate(int parameterIndex, DependencyType type) { + getVariable(parameterIndex).propagate(type); + return this; + } + public void use() { if (!used) { used = true; diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java index 657f11598..081ab3822 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyDependency.java @@ -108,14 +108,26 @@ public class JavaScriptBodyDependency extends AbstractDependencyListener { private void includeDefaultDependencies(DependencyAgent agent, CallLocation location) { agent.linkMethod(JavaScriptConvGenerator.fromJsMethod, location).use(); agent.linkMethod(JavaScriptConvGenerator.toJsMethod, location).use(); - agent.linkMethod(JavaScriptConvGenerator.intValueMethod, location).use(); + + agent.linkMethod(JavaScriptConvGenerator.intValueMethod, location).propagate(0, Integer.class).use(); agent.linkMethod(JavaScriptConvGenerator.valueOfIntMethod, location).use(); - agent.linkMethod(JavaScriptConvGenerator.booleanValueMethod, location).use(); + + agent.linkMethod(JavaScriptConvGenerator.booleanValueMethod, location).propagate(0, Boolean.class).use(); agent.linkMethod(JavaScriptConvGenerator.valueOfBooleanMethod, location).use(); - agent.linkMethod(JavaScriptConvGenerator.doubleValueMethod, location).use(); + + agent.linkMethod(JavaScriptConvGenerator.doubleValueMethod, location).propagate(0, Double.class).use(); agent.linkMethod(JavaScriptConvGenerator.valueOfDoubleMethod, location).use(); - agent.linkMethod(JavaScriptConvGenerator.charValueMethod, location).use(); + + agent.linkMethod(JavaScriptConvGenerator.charValueMethod, location).propagate(0, Character.class).use(); agent.linkMethod(JavaScriptConvGenerator.valueOfCharMethod, location).use(); + + agent.linkMethod(JavaScriptConvGenerator.byteValueMethod, location).propagate(0, Byte.class).use(); + agent.linkMethod(JavaScriptConvGenerator.valueOfByteMethod, location).use(); + + agent.linkMethod(JavaScriptConvGenerator.shortValueMethod, location).propagate(0, Short.class).use(); + agent.linkMethod(JavaScriptConvGenerator.valueOfShortMethod, location).use(); + + agent.linkMethod(JavaScriptConvGenerator.valueOfLongMethod, location).use(); } private static MethodReader findMethod(ClassReaderSource classSource, String clsName, MethodDescriptor desc) { diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConvGenerator.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConvGenerator.java index d0e5ebfb6..0776dcf78 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConvGenerator.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConvGenerator.java @@ -28,10 +28,18 @@ import org.teavm.model.*; public class JavaScriptConvGenerator implements Generator { static final MethodReference intValueMethod = new MethodReference(Integer.class, "intValue", int.class); static final MethodReference booleanValueMethod = new MethodReference(Boolean.class, "booleanValue", boolean.class); + static final MethodReference byteValueMethod = new MethodReference(Byte.class, "byteValue", byte.class); + static final MethodReference shortValueMethod = new MethodReference(Byte.class, "shortValue", short.class); static final MethodReference doubleValueMethod = new MethodReference(Double.class, "doubleValue", double.class); static final MethodReference charValueMethod = new MethodReference(Character.class, "charValue", char.class); + static final MethodReference valueOfByteMethod = new MethodReference(Byte.class, "valueOf", + byte.class, Byte.class); + static final MethodReference valueOfShortMethod = new MethodReference(Short.class, "valueOf", + short.class, Short.class); static final MethodReference valueOfIntMethod = new MethodReference(Integer.class, "valueOf", int.class, Integer.class); + static final MethodReference valueOfLongMethod = new MethodReference(Long.class, "valueOf", + long.class, Long.class); static final MethodReference valueOfBooleanMethod = new MethodReference(Boolean.class, "valueOf", boolean.class, Boolean.class); static final MethodReference valueOfDoubleMethod = new MethodReference(Double.class, "valueOf", @@ -59,8 +67,10 @@ public class JavaScriptConvGenerator implements Generator { String obj = context.getParameterName(1); writer.append("if (" + obj + " === null || " + obj + " === undefined) {").softNewLine().indent(); writer.append("return " + obj + ";").softNewLine(); + writer.outdent().append("} else if (typeof " + obj + " === 'number') {").indent().softNewLine(); writer.append("return " + obj + ";").softNewLine(); + writer.outdent().append("} else if (" + obj + ".constructor.$meta && " + obj + ".constructor.$meta.item) {") .indent().softNewLine(); writer.append("var arr = new Array(" + obj + ".data.length);").softNewLine(); @@ -68,23 +78,38 @@ public class JavaScriptConvGenerator implements Generator { writer.append("arr[i] = ").appendMethodBody(toJsMethod).append("(" + obj + ".data[i]);").softNewLine(); writer.outdent().append("}").softNewLine(); writer.append("return arr;").softNewLine(); + writer.outdent().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.Byte") + .append(") {").indent().softNewLine(); + writer.append("return ").appendMethodBody(byteValueMethod).append("(" + obj + ")|0;").softNewLine(); + + writer.outdent().append("} else if (" + obj + ".constructor === ").appendClass("java.lang.Short") + .append(") {").indent().softNewLine(); + writer.append("return ").appendMethodBody(shortValueMethod).append("(" + obj + ")|0;").softNewLine(); + writer.outdent().append("} else if (" + obj + ".constructor === ").appendClass("java.lang.Integer") .append(") {").indent().softNewLine(); writer.append("return ").appendMethodBody(intValueMethod).append("(" + obj + ")|0;").softNewLine(); + writer.outdent().append("} else if (" + obj + ".constructor === ").appendClass("java.lang.Boolean") .append(") {").indent().softNewLine(); writer.append("return ").appendMethodBody(booleanValueMethod).append("(" + obj + ")!==0;").softNewLine(); + writer.outdent().append("} else if (" + obj + ".constructor === ").appendClass("java.lang.Double") .append(") {").indent().softNewLine(); writer.append("return ").appendMethodBody(doubleValueMethod).append("(" + obj + ");").softNewLine(); + writer.outdent().append("} else if (" + obj + ".constructor === ").appendClass("java.lang.Character") .append(") {").indent().softNewLine(); writer.append("return ").appendMethodBody(charValueMethod).append("(" + obj + ");").softNewLine(); + writer.outdent().append("} else {").indent().softNewLine(); writer.append("return " + obj + ";").softNewLine(); + writer.outdent().append("}").softNewLine(); } @@ -101,30 +126,54 @@ public class JavaScriptConvGenerator implements Generator { type + ".$meta.item);").softNewLine(); writer.outdent().append("}").softNewLine(); writer.append("return arr;").softNewLine(); + writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.String") .append(") {").indent().softNewLine(); writer.append("return $rt_str(" + obj + ");").softNewLine(); - writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Integer") - .append(") {").indent().softNewLine(); - writer.append("return ").appendMethodBody(valueOfIntMethod).append("(" + obj + ");").softNewLine(); - writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Double") - .append(") {").indent().softNewLine(); - writer.append("return ").appendMethodBody(valueOfDoubleMethod).append("(" + obj + ");").softNewLine(); - writer.outdent().append("} else if (" + type + " === $rt_intcls() || " + type + " === $rt_bytecls() || " + - type + " === $rt_shortcls()) {").indent().softNewLine(); - writer.append("return " + obj + "|0;").softNewLine(); - writer.outdent().append("} else if (" + type + " === $rt_doublecls() || " + type + " == $rt_floatcls()) {") - .indent().softNewLine(); - writer.append("return " + obj + ";").softNewLine(); + writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Boolean") .append(") {").indent().softNewLine(); writer.append("return ").appendMethodBody(valueOfBooleanMethod).append("(" + obj + "?1:0);").softNewLine(); + writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Character") .append(") {").indent().softNewLine(); writer.append("return ").appendMethodBody(valueOfCharMethod).append("(typeof " + obj + " === 'number' ? " + obj + "0xFFFF : " + obj + ".charCodeAt(0));").softNewLine(); + + writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Byte") + .append(") {").indent().softNewLine(); + writer.append("return ").appendMethodBody(valueOfByteMethod).append("(" + obj + "|0);").softNewLine(); + + writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Short") + .append(") {").indent().softNewLine(); + writer.append("return ").appendMethodBody(valueOfShortMethod).append("(" + obj + "|0);").softNewLine(); + + writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Integer") + .append(") {").indent().softNewLine(); + writer.append("return ").appendMethodBody(valueOfIntMethod).append("(" + obj + "|0);").softNewLine(); + + writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Long") + .append(") {").indent().softNewLine(); + writer.append("return ").appendMethodBody(valueOfLongMethod).append("(Long_fromInt(" + obj + "|0));") + .softNewLine(); + + writer.outdent().append("} else if (" + type + " === ").appendClass("java.lang.Double") + .append(") {").indent().softNewLine(); + writer.append("return ").appendMethodBody(valueOfDoubleMethod).append("(" + obj + ");").softNewLine(); + + writer.outdent().append("} else if (" + type + " === $rt_intcls() || " + type + " === $rt_bytecls() || " + + type + " === $rt_shortcls() ||" + type + " == $rt_charcls()) {").indent().softNewLine(); + writer.append("return " + obj + "|0;").softNewLine(); + + writer.outdent().append("} else if (" + type + " === $rt_longcls()) {").indent().softNewLine(); + writer.append("return Long_fromInt(" + obj + "|0);").softNewLine(); + + writer.outdent().append("} else if (" + type + " === $rt_doublecls() || " + type + " == $rt_floatcls()) {") + .indent().softNewLine(); + writer.append("return " + obj + ";").softNewLine(); writer.outdent().append("} else if (" + type + " === $rt_booleancls()) {").indent().softNewLine(); writer.append("return " + obj + "?1:0;").softNewLine(); + writer.outdent().append("} else if (" + obj + " instanceof Array) {").indent().softNewLine(); writer.append("var arr = $rt_createArray($rt_objcls(), " + obj + ".length);").softNewLine(); writer.append("for (var i = 0; i < arr.data.length; ++i) {").indent().softNewLine(); @@ -132,14 +181,17 @@ public class JavaScriptConvGenerator implements Generator { .softNewLine(); writer.outdent().append("}").softNewLine(); writer.append("return arr;").softNewLine(); + writer.outdent().append("} else if (typeof " + obj + " === 'string') {").indent().softNewLine(); writer.append("return $rt_str(" + obj + ");").softNewLine(); + writer.outdent().append("} else if (typeof " + obj + " === 'number') {").indent().softNewLine(); writer.append("if (" + obj + "|0 === " + obj + ") {").indent().softNewLine(); writer.append("return ").appendMethodBody(valueOfIntMethod).append("(" + obj + ");").softNewLine(); writer.outdent().append("} else {").indent().softNewLine(); writer.append("return ").appendMethodBody(valueOfDoubleMethod).append("(" + obj + ");").softNewLine(); writer.outdent().append("}").softNewLine(); + writer.outdent().append("} else if (typeof " + obj + " === 'boolean') {").indent().softNewLine(); writer.append("return ").appendMethodBody(valueOfBooleanMethod).append("(" + obj + "?1:0);").softNewLine(); writer.outdent().append("} else {").indent().softNewLine();