diff --git a/teavm-core/src/main/java/org/teavm/codegen/DefaultNamingStrategy.java b/teavm-core/src/main/java/org/teavm/codegen/DefaultNamingStrategy.java index f4cbf3a1e..80123b3c5 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/DefaultNamingStrategy.java +++ b/teavm-core/src/main/java/org/teavm/codegen/DefaultNamingStrategy.java @@ -57,15 +57,15 @@ public class DefaultNamingStrategy implements NamingStrategy { @Override public String getNameFor(MethodReference method) { - return getNameFor(method, false); + return getNameFor(method, 'S'); } @Override public String getNameForAsync(MethodReference method) throws NamingException { - return getNameFor(method, true); + return getNameFor(method, 'A'); } - private String getNameFor(MethodReference method, boolean async) { + private String getNameFor(MethodReference method, char classifier) { MethodReference origMethod = method; method = getRealMethod(method); if (method == null) { @@ -76,7 +76,7 @@ public class DefaultNamingStrategy implements NamingStrategy { if (methodHolder.hasModifier(ElementModifier.STATIC) || method.getDescriptor().getName().equals("") || methodHolder.getLevel() == AccessLevel.PRIVATE) { - String key = (async ? "A" : "S") + method.toString(); + String key = classifier + method.toString(); String alias = privateAliases.get(key); if (alias == null) { alias = aliasProvider.getAlias(method); @@ -84,7 +84,7 @@ public class DefaultNamingStrategy implements NamingStrategy { } return alias; } else { - String key = (async ? "A" : "S") + method.getDescriptor().toString(); + String key = classifier + method.getDescriptor().toString(); String alias = aliases.get(key); if (alias == null) { alias = aliasProvider.getAlias(method); @@ -96,15 +96,24 @@ public class DefaultNamingStrategy implements NamingStrategy { @Override public String getFullNameFor(MethodReference method) throws NamingException { + return getFullNameFor(method, 'S'); + } + + @Override + public String getNameForInit(MethodReference method) throws NamingException { + return getFullNameFor(method, 'I'); + } + + private String getFullNameFor(MethodReference method, char classifier) throws NamingException { MethodReference originalMethod = method; if (!minifying) { - return getNameFor(method.getClassName()) + "_" + getNameFor(method); + return getNameFor(method.getClassName()) + "_" + getNameFor(method, classifier); } method = getRealMethod(method); if (method == null) { throw new NamingException("Can't provide name for method as it was not found: " + originalMethod); } - String key = method.toString(); + String key = classifier + method.toString(); String alias = privateAliases.get(key); if (alias == null) { alias = aliasProvider.getAlias(method); diff --git a/teavm-core/src/main/java/org/teavm/codegen/NamingStrategy.java b/teavm-core/src/main/java/org/teavm/codegen/NamingStrategy.java index 9ac73ecfe..a2a3d2eb9 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/NamingStrategy.java +++ b/teavm-core/src/main/java/org/teavm/codegen/NamingStrategy.java @@ -29,6 +29,8 @@ public interface NamingStrategy { String getNameForAsync(MethodReference method) throws NamingException; + String getNameForInit(MethodReference method) throws NamingException; + String getFullNameFor(MethodReference method) throws NamingException; String getNameFor(FieldReference field) throws NamingException; diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index f034f4cc7..04bfce9d2 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -213,8 +213,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.append("for (var i = 0; i < str.length; i = (i + 1) | 0) {").indent().softNewLine(); writer.append("charsBuffer[i] = str.charCodeAt(i) & 0xFFFF;").softNewLine(); writer.outdent().append("}").softNewLine(); - writer.append("return ").appendClass("java.lang.String").append(".") - .appendMethod(stringCons).append("(characters);").softNewLine(); + writer.append("return ").append(naming.getNameForInit(stringCons)).append("(characters);").softNewLine(); writer.outdent().append("}").newLine(); } @@ -235,11 +234,10 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } private void renderRuntimeNullCheck() throws IOException { - String npe = "java.lang.NullPointerException"; writer.append("function $rt_nullCheck(val) {").indent().softNewLine(); writer.append("if (val === null) {").indent().softNewLine(); - writer.append("$rt_throw(").appendClass(npe).append('.').appendMethod(npe, "", ValueType.VOID) - .append("());").softNewLine(); + writer.append("$rt_throw(").append(naming.getNameForInit(new MethodReference(NullPointerException.class, + "", void.class))).append("());").softNewLine(); writer.outdent().append("}").softNewLine(); writer.append("return val;").softNewLine(); writer.outdent().append("}").newLine(); @@ -293,6 +291,23 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext .append(constantToString(value)).append(";").softNewLine(); } + List nonInitMethods = new ArrayList<>(); + List virtualMethods = new ArrayList<>(); + MethodHolder clinit = classSource.get(cls.getName()).getMethod( + new MethodDescriptor("", ValueType.VOID)); + List stubNames = new ArrayList<>(); + List clinitMethods = new ArrayList<>(); + for (MethodNode method : cls.getMethods()) { + if (!method.getModifiers().contains(NodeModifier.STATIC) && + !method.getReference().getName().equals("")) { + nonInitMethods.add(method); + } else { + clinitMethods.add(method); + stubNames.add(naming.getFullNameFor(method.getReference())); + } + } + boolean needsClinit = clinit != null || !clinitMethods.isEmpty(); + writer.append("$rt_declClass(").appendClass(cls.getName()).append(",").ws().append("{") .indent().softNewLine(); writer.append("name").ws().append(":").ws().append("\"").append(escapeString(cls.getName())) @@ -315,41 +330,36 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.append(",").softNewLine(); writer.append("superclass").ws().append(":").ws().appendClass(cls.getParentName()); } - if (!cls.getModifiers().contains(NodeModifier.INTERFACE)) { + if (!cls.getModifiers().contains(NodeModifier.INTERFACE) && needsClinit) { writer.append(",").softNewLine().append("clinit").ws().append(":").ws() .append("function()").ws().append("{").ws() .appendClass(cls.getName()).append("_$clinit();").ws().append("}"); } writer.ws().append("});").newLine().outdent(); - List nonInitMethods = new ArrayList<>(); - List virtualMethods = new ArrayList<>(); - writer.append("function ").appendClass(cls.getName()).append("_$clinit()").ws() - .append("{").softNewLine().indent(); - writer.appendClass(cls.getName()).append("_$clinit").ws().append("=").ws() - .append("function(){};").newLine(); - List stubNames = new ArrayList<>(); - for (MethodNode method : cls.getMethods()) { - if (!method.getModifiers().contains(NodeModifier.STATIC) && - !method.getReference().getName().equals("")) { - nonInitMethods.add(method); - } else { + if (needsClinit) { + writer.append("function ").appendClass(cls.getName()).append("_$clinit()").ws() + .append("{").softNewLine().indent(); + writer.appendClass(cls.getName()).append("_$clinit").ws().append("=").ws() + .append("function(){};").newLine(); + for (MethodNode method : clinitMethods) { renderBody(method, true); - stubNames.add(naming.getFullNameFor(method.getReference())); } + if (clinit != null) { + writer.appendMethodBody(new MethodReference(cls.getName(), clinit.getDescriptor())) + .append("();").softNewLine(); + } + writer.outdent().append("}").newLine(); } - MethodHolder methodHolder = classSource.get(cls.getName()).getMethod( - new MethodDescriptor("", ValueType.VOID)); - if (methodHolder != null) { - writer.appendMethodBody(new MethodReference(cls.getName(), methodHolder.getDescriptor())) - .append("();").softNewLine(); - } - writer.outdent().append("}").newLine(); if (!cls.getModifiers().contains(NodeModifier.INTERFACE)) { for (MethodNode method : cls.getMethods()) { cls.getMethods(); if (!method.getModifiers().contains(NodeModifier.STATIC)) { - virtualMethods.add(method); + if (method.getReference().getName().equals("")) { + renderInitializer(method); + } else { + virtualMethods.add(method); + } } else if (method.isOriginalNamePreserved()) { renderStaticDeclaration(method); } @@ -407,7 +417,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext private void renderInitializer(MethodNode method) throws IOException { MethodReference ref = method.getReference(); debugEmitter.emitMethod(ref.getDescriptor()); - writer.appendClass(ref.getClassName()).append(".").appendMethod(ref).ws().append("=").ws().append("function("); + writer.append("function ").append(naming.getNameForInit(ref)).append("("); for (int i = 1; i <= ref.parameterCount(); ++i) { if (i > 1) { writer.append(",").ws(); @@ -417,11 +427,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.append(")").ws().append("{").newLine().indent(); writer.append("var result").ws().append("=").ws().append("new ").appendClass( ref.getClassName()).append("();").softNewLine(); - writer.append("result.").appendMethod(ref).append("("); + writer.append(naming.getFullNameFor(ref)).append("(result"); for (int i = 1; i <= ref.parameterCount(); ++i) { - if (i > 1) { - writer.append(",").ws(); - } + writer.append(",").ws(); writer.append(variableName(i)); } writer.append(");").softNewLine(); @@ -454,11 +462,18 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.append("\"").append(methodName).append("\""); } writer.append(",").ws().append("function("); + List args = new ArrayList<>(); for (int i = 1; i <= ref.parameterCount(); ++i) { - if (i > 1) { + args.add(variableName(i)); + } + if (method.isAsync()) { + args.add("$return"); + } + for (int i = 0; i < args.size(); ++i) { + if (i > 0) { writer.append(",").ws(); } - writer.append(variableName(i)); + writer.append(args.get(i)); } writer.append(")").ws().append("{").ws(); if (ref.getDescriptor().getResultType() != ValueType.VOID) { @@ -466,8 +481,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } writer.appendMethodBody(ref).append("("); writer.append("this"); - for (int i = 1; i <= ref.parameterCount(); ++i) { - writer.append(",").ws().append(variableName(i)); + for (int i = 0; i < args.size(); ++i) { + writer.append(",").ws().append(args.get(i)); } writer.append(");").ws().append("}"); debugEmitter.emitMethod(null); @@ -1438,7 +1453,6 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext if (expr.getType() == InvocationType.DYNAMIC) { expr.getArguments().get(0).acceptVisitor(this); } - String className = naming.getNameFor(expr.getMethod().getClassName()); String name = expr.getAsyncTarget() == null ? naming.getNameFor(expr.getMethod()) : naming.getNameForAsync(expr.getMethod()); String fullName = naming.getFullNameFor(expr.getMethod()); @@ -1484,7 +1498,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext virtual = true; break; case CONSTRUCTOR: - writer.append(className).append(".").append(name).append("("); + writer.append(naming.getNameForInit(expr.getMethod())).append("("); prevCallSite = debugEmitter.emitCallSite(); for (int i = 0; i < expr.getArguments().size(); ++i) { if (i > 0) { diff --git a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js index d6793042b..ae71f1784 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -377,7 +377,7 @@ function $rt_declClass(cls, data) { cls.$meta.binaryName = "L" + data.name + ";"; cls.$meta.enum = data.enum; cls.prototype.constructor = cls; - cls.$clinit = data.clinit; + cls.$clinit = data.clinit ? data.clinit : function() {}; } function $rt_virtualMethods(cls) { for (var i = 1; i < arguments.length; i += 2) {