diff --git a/pom.xml b/pom.xml index 5fe03e8cd..6937d906f 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,7 @@ teavm-platform teavm-cli teavm-chrome-rdp + teavm-tests diff --git a/teavm-classlib/pom.xml b/teavm-classlib/pom.xml index 6dac0cd24..2624f6ff9 100644 --- a/teavm-classlib/pom.xml +++ b/teavm-classlib/pom.xml @@ -49,6 +49,16 @@ teavm-core ${project.version} + + org.teavm + teavm-jso + ${project.version} + + + org.teavm + teavm-dom + ${project.version} + com.google.code.gson gson @@ -74,34 +84,6 @@ - - org.teavm - teavm-maven-plugin - ${project.version} - - - org.teavm - teavm-platform - ${project.version} - - - - - generate-javascript-tests - - build-test-javascript - - process-test-classes - - false - - en, en_US, en_GB, ru, ru_RU - - ${teavm.classlib.test.incremental} - - - - org.codehaus.mojo exec-maven-plugin @@ -135,15 +117,6 @@ - - org.apache.maven.plugins - maven-surefire-plugin - - - org/teavm/platform/metadata/*.java - - - org.apache.maven.plugins maven-source-plugin diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassMetadataGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassMetadataGenerator.java new file mode 100644 index 000000000..30842e676 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/DeclaringClassMetadataGenerator.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 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.util.HashMap; +import java.util.Map; +import org.teavm.model.ClassReader; +import org.teavm.model.MethodReference; +import org.teavm.platform.metadata.*; + +/** + * + * @author Alexey Andreev + */ +public class DeclaringClassMetadataGenerator implements ClassScopedMetadataGenerator { + @Override + public Map generateMetadata(MetadataGeneratorContext context, MethodReference method) { + Map result = new HashMap<>(); + for (String clsName : context.getClassSource().getClassNames()) { + ClassReader cls = context.getClassSource().get(clsName); + if (cls.getOwnerName() != null) { + result.put(clsName, context.createClassResource(cls.getOwnerName())); + } + } + return result; + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java index 4d3d853bb..895bf3d49 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/JCLPlugin.java @@ -18,6 +18,7 @@ package org.teavm.classlib.impl; import java.util.ServiceLoader; import org.teavm.classlib.impl.unicode.CLDRReader; import org.teavm.model.MethodReference; +import org.teavm.platform.PlatformClass; import org.teavm.vm.spi.TeaVMHost; import org.teavm.vm.spi.TeaVMPlugin; @@ -28,15 +29,11 @@ import org.teavm.vm.spi.TeaVMPlugin; public class JCLPlugin implements TeaVMPlugin { @Override public void install(TeaVMHost host) { - host.add(new EnumDependencySupport()); - 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(ServiceLoader.class, "loadServices", - Class.class, Object[].class); + PlatformClass.class, Object[].class); host.add(loadServicesMethod, serviceLoaderSupp); JavacSupport javacSupport = new JavacSupport(); host.add(javacSupport); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/ServiceLoaderSupport.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/ServiceLoaderSupport.java index 48a784c35..f019593a7 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/ServiceLoaderSupport.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/ServiceLoaderSupport.java @@ -23,8 +23,8 @@ import java.net.URL; import java.util.*; import org.teavm.codegen.SourceWriter; import org.teavm.dependency.*; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.CallLocation; import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodReference; @@ -65,7 +65,7 @@ public class ServiceLoaderSupport implements Generator, DependencyListener { } writer.outdent().append("}").softNewLine(); String param = context.getParameterName(1); - writer.append("var cls = " + param + ".$data;").softNewLine(); + writer.append("var cls = " + param + ";").softNewLine(); writer.append("if (!cls.$$serviceList$$) {").indent().softNewLine(); writer.append("return $rt_createArray($rt_objcls(), 0);").softNewLine(); writer.outdent().append("}").softNewLine(); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/CharacterMetadataGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/CharacterMetadataGenerator.java new file mode 100644 index 000000000..ea21a6a5a --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/CharacterMetadataGenerator.java @@ -0,0 +1,54 @@ +/* + * Copyright 2015 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.java.lang; + +import org.teavm.classlib.impl.unicode.UnicodeHelper; +import org.teavm.classlib.impl.unicode.UnicodeSupport; +import org.teavm.model.MethodReference; +import org.teavm.platform.metadata.MetadataGenerator; +import org.teavm.platform.metadata.MetadataGeneratorContext; +import org.teavm.platform.metadata.Resource; +import org.teavm.platform.metadata.StringResource; + +/** + * + * @author Alexey Andreev + */ +public class CharacterMetadataGenerator implements MetadataGenerator { + @Override + public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) { + switch (method.getName()) { + case "obtainDigitMapping": + return generateObtainDigitMapping(context); + case "obtainClasses": + return generateObtainClasses(context); + default: + return null; + } + } + + private Resource generateObtainDigitMapping(MetadataGeneratorContext context) { + StringResource res = context.createResource(StringResource.class); + res.setValue(UnicodeHelper.encodeIntByte(UnicodeSupport.getDigitValues())); + return res; + } + + private Resource generateObtainClasses(MetadataGeneratorContext context) { + StringResource res = context.createResource(StringResource.class); + res.setValue(UnicodeHelper.compressRle(UnicodeSupport.getClasses())); + return res; + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/CharacterNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/CharacterNativeGenerator.java deleted file mode 100644 index 4031d1cfe..000000000 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/CharacterNativeGenerator.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.java.lang; - -import java.io.IOException; -import org.teavm.classlib.impl.unicode.UnicodeHelper; -import org.teavm.classlib.impl.unicode.UnicodeSupport; -import org.teavm.codegen.SourceWriter; -import org.teavm.dependency.DependencyAgent; -import org.teavm.dependency.DependencyPlugin; -import org.teavm.dependency.MethodDependency; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; -import org.teavm.model.CallLocation; -import org.teavm.model.MethodReference; - -/** - * - * @author Alexey Andreev - */ -public class CharacterNativeGenerator implements Generator, DependencyPlugin { - @Override - public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { - switch (methodRef.getName()) { - case "toLowerCase": - writer.append("return String.fromCharCode(").append(context.getParameterName(1)) - .append(").toLowerCase().charCodeAt(0)|0;").softNewLine(); - break; - case "toUpperCase": - writer.append("return String.fromCharCode(").append(context.getParameterName(1)) - .append(").toUpperCase().charCodeAt(0)|0;").softNewLine(); - break; - case "obtainDigitMapping": - generateObtainDigitMapping(writer); - break; - case "obtainClasses": - generateObtainClasses(writer); - break; - } - } - - @Override - public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) { - switch (method.getReference().getName()) { - case "obtainDigitMapping": - case "obtainClasses": - method.getResult().propagate(agent.getType("java.lang.String")); - break; - } - } - - private void generateObtainDigitMapping(SourceWriter writer) throws IOException { - String str = UnicodeHelper.encodeIntByte(UnicodeSupport.getDigitValues()); - writer.append("return $rt_str("); - splitString(writer, str); - writer.append(");").softNewLine(); - } - - private void generateObtainClasses(SourceWriter writer) throws IOException { - String str = UnicodeHelper.compressRle(UnicodeSupport.getClasses()); - writer.append("return $rt_str("); - splitString(writer, str); - writer.append(");").softNewLine(); - } - - private void splitString(SourceWriter writer, String str) throws IOException { - for (int i = 0; i < str.length(); i += 512) { - if (i > 0) { - writer.ws().append("+").newLine(); - } - int j = Math.min(i + 512, str.length()); - writer.append("\"").append(str.substring(i, j)).append("\""); - } - } -} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java deleted file mode 100644 index 53d7aba14..000000000 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ClassNativeGenerator.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2013 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.java.lang; - -import java.io.IOException; -import org.teavm.codegen.SourceWriter; -import org.teavm.dependency.DependencyAgent; -import org.teavm.dependency.DependencyPlugin; -import org.teavm.dependency.MethodDependency; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; -import org.teavm.javascript.ni.Injector; -import org.teavm.javascript.ni.InjectorContext; -import org.teavm.model.*; - -/** - * - * @author Alexey Andreev - */ -public class ClassNativeGenerator implements Generator, Injector, DependencyPlugin { - @Override - public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) - throws IOException { - switch (methodRef.getName()) { - case "getComponentType0": - generateGetComponentType(context, writer); - break; - case "getSuperclass": - generateGetSuperclass(context, writer); - break; - case "forNameImpl": - generateForName(context, writer); - break; - case "newInstance": - generateNewInstance(context, writer); - break; - case "getDeclaringClass": - generateGetDeclaringClass(context, writer); - break; - } - } - - private void generateGetComponentType(GeneratorContext context, SourceWriter writer) throws IOException { - String thisArg = context.getParameterName(0); - writer.append("var item = " + thisArg + ".$data.$meta.item;").softNewLine(); - writer.append("return item != null ? $rt_cls(item) : null;").softNewLine(); - } - - private void generateGetSuperclass(GeneratorContext context, SourceWriter writer) throws IOException { - String thisArg = context.getParameterName(0); - writer.append("var superclass = " + thisArg + ".$data.$meta.superclass;").softNewLine(); - writer.append("return superclass ? $rt_cls(superclass) : null;").softNewLine(); - } - - @Override - public void generate(InjectorContext context, MethodReference methodRef) throws IOException { - switch (methodRef.getName()) { - case "isInstance": - generateIsInstance(context); - break; - case "isAssignableFrom": - generateIsAssignableFrom(context); - break; - case "voidClass": - context.getWriter().append("$rt_cls($rt_voidcls())"); - break; - case "booleanClass": - context.getWriter().append("$rt_cls($rt_booleancls())"); - break; - case "charClass": - context.getWriter().append("$rt_cls($rt_charcls())"); - break; - case "byteClass": - context.getWriter().append("$rt_cls($rt_bytecls())"); - break; - case "shortClass": - context.getWriter().append("$rt_cls($rt_shortcls())"); - break; - case "intClass": - context.getWriter().append("$rt_cls($rt_intcls())"); - break; - case "longClass": - context.getWriter().append("$rt_cls($rt_longcls())"); - break; - case "floatClass": - context.getWriter().append("$rt_cls($rt_floatcls())"); - break; - case "doubleClass": - context.getWriter().append("$rt_cls($rt_doublecls())"); - break; - case "wrapClass": - context.writeExpr(context.getArgument(0)); - break; - case "getEnumConstantsImpl": - context.writeExpr(context.getArgument(0)); - context.getWriter().append(".$data.values()"); - break; - } - } - - private void generateIsAssignableFrom(InjectorContext context) throws IOException { - SourceWriter writer = context.getWriter(); - writer.append("$rt_isAssignable("); - context.writeExpr(context.getArgument(1)); - writer.append(".$data,").ws(); - context.writeExpr(context.getArgument(0)); - writer.append(".$data)"); - } - - private void generateIsInstance(InjectorContext context) throws IOException { - SourceWriter writer = context.getWriter(); - writer.append("$rt_isInstance("); - context.writeExpr(context.getArgument(1)); - writer.append(",").ws(); - context.writeExpr(context.getArgument(0)); - writer.append(".$data)"); - } - - private void generateForName(GeneratorContext context, SourceWriter writer) throws IOException { - String param = context.getParameterName(1); - writer.append("switch ($rt_ustr(" + param + ")) {").softNewLine().indent(); - for (String name : context.getClassSource().getClassNames()) { - writer.append("case \"" + name + "\": ").appendClass(name).append(".$clinit(); ") - .append("return $rt_cls(").appendClass(name).append(");").softNewLine(); - } - writer.append("default: return null;").softNewLine(); - writer.outdent().append("}").softNewLine(); - } - - private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException { - String self = context.getParameterName(0); - writer.append("if (!").appendClass("java.lang.Class").append(".$$constructors$$) {").indent().softNewLine(); - writer.appendClass("java.lang.Class").append(".$$constructors$$ = true;").softNewLine(); - for (String clsName : context.getClassSource().getClassNames()) { - ClassReader cls = context.getClassSource().get(clsName); - MethodReader method = cls.getMethod(new MethodDescriptor("", ValueType.VOID)); - if (method != null) { - writer.appendClass(clsName).append(".$$constructor$$ = ").appendMethodBody(method.getReference()) - .append(";").softNewLine(); - } - } - writer.outdent().append("}").softNewLine(); - writer.append("var cls = " + self + ".$data;").softNewLine(); - writer.append("var ctor = cls.$$constructor$$;").softNewLine(); - writer.append("if (!ctor) {").indent().softNewLine(); - writer.append("var ex = new ").appendClass(InstantiationException.class.getName()).append("();").softNewLine(); - writer.appendMethodBody(new MethodReference(InstantiationException.class.getName(), new MethodDescriptor( - "", ValueType.VOID))).append("(ex);").softNewLine(); - writer.append("$rt_throw(ex);").softNewLine(); - writer.outdent().append("}").softNewLine(); - writer.append("var instance = new cls();").softNewLine(); - writer.append("ctor(instance);").softNewLine(); - writer.append("return instance;").softNewLine(); - } - - private void generateGetDeclaringClass(GeneratorContext context, SourceWriter writer) throws IOException { - String self = context.getParameterName(0); - writer.append("if (!").appendClass("java.lang.Class").append(".$$owners$$) {").indent().softNewLine(); - writer.appendClass("java.lang.Class").append(".$$owners$$ = true;").softNewLine(); - for (String clsName : context.getClassSource().getClassNames()) { - ClassReader cls = context.getClassSource().get(clsName); - writer.appendClass(clsName).append(".$$owner$$ = "); - if (cls.getOwnerName() != null) { - writer.appendClass(cls.getOwnerName()); - } else { - writer.append("null"); - } - writer.append(";").softNewLine(); - } - writer.outdent().append("}").softNewLine(); - writer.append("var cls = " + self + ".$data;").softNewLine(); - writer.append("return cls.$$owner$$ != null ? $rt_cls(cls.$$owner$$) : null;").softNewLine(); - } - - @Override - public void methodAchieved(DependencyAgent agent, MethodDependency graph, CallLocation location) { - switch (graph.getReference().getName()) { - case "voidClass": - case "booleanClass": - case "byteClass": - case "shortClass": - case "charClass": - case "intClass": - case "longClass": - case "floatClass": - case "doubleClass": - case "wrapClass": - case "getSuperclass": - case "getComponentType0": - case "forNameImpl": - case "getDeclaringClass": - graph.getResult().propagate(agent.getType("java.lang.Class")); - break; - case "getName": - graph.getResult().propagate(agent.getType("java.lang.String")); - break; - case "newInstance": - agent.linkMethod(new MethodReference(InstantiationException.class, "", void.class), - location).use(); - break; - } - } -} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ConsoleOutputStreamGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ConsoleOutputStreamGenerator.java deleted file mode 100644 index 8fbd93581..000000000 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ConsoleOutputStreamGenerator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2013 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.java.lang; - -import java.io.IOException; -import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; -import org.teavm.model.MethodReference; - -/** - * - * @author Alexey Andreev - */ -public class ConsoleOutputStreamGenerator implements Generator { - @Override - public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { - if (methodRef.getClassName().endsWith("_stderr")) { - if (methodRef.getName().equals("write")) { - writer.append("$rt_putStderr(").append(context.getParameterName(1)).append(");").softNewLine(); - } - } else if (methodRef.getClassName().endsWith("_stdout")) { - if (methodRef.getName().equals("write")) { - writer.append("$rt_putStdout(").append(context.getParameterName(1)).append(");").softNewLine(); - } - } - } -} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/DoubleNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/DoubleNativeGenerator.java index 6c30c9617..db26c4338 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/DoubleNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/DoubleNativeGenerator.java @@ -17,10 +17,10 @@ package org.teavm.classlib.java.lang; import java.io.IOException; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; -import org.teavm.javascript.ni.Injector; -import org.teavm.javascript.ni.InjectorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; +import org.teavm.javascript.spi.Injector; +import org.teavm.javascript.spi.InjectorContext; import org.teavm.model.MethodReference; /** diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/FloatNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/FloatNativeGenerator.java index 2ebcd6228..1aca3eb1c 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/FloatNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/FloatNativeGenerator.java @@ -17,10 +17,10 @@ package org.teavm.classlib.java.lang; import java.io.IOException; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; -import org.teavm.javascript.ni.Injector; -import org.teavm.javascript.ni.InjectorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; +import org.teavm.javascript.spi.Injector; +import org.teavm.javascript.spi.InjectorContext; import org.teavm.model.MethodReference; /** diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/LongNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/LongNativeGenerator.java index 4a195bfbf..e82de0450 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/LongNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/LongNativeGenerator.java @@ -17,8 +17,8 @@ package org.teavm.classlib.java.lang; import java.io.IOException; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.MethodReference; /** diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/MathNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/MathNativeGenerator.java index a3805d412..25931041d 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/MathNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/MathNativeGenerator.java @@ -17,8 +17,8 @@ package org.teavm.classlib.java.lang; import java.io.IOException; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.MethodReference; /** diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ObjectNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ObjectNativeGenerator.java deleted file mode 100644 index e90cb051d..000000000 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ObjectNativeGenerator.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2013 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.java.lang; - -import java.io.IOException; -import org.teavm.codegen.SourceWriter; -import org.teavm.dependency.*; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; -import org.teavm.javascript.ni.Injector; -import org.teavm.javascript.ni.InjectorContext; -import org.teavm.model.CallLocation; -import org.teavm.model.MethodReference; - -/** - * - * @author Alexey Andreev - */ -public class ObjectNativeGenerator implements Generator, Injector, DependencyPlugin { - @Override - public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { - switch (methodRef.getDescriptor().getName()) { - case "": - generateInit(context, writer); - break; - case "hashCode": - case "identity": - generateHashCode(context, writer); - break; - case "clone": - generateClone(context, writer); - break; - case "wait": - generateWait(context, writer); - break; - case "notify": - generateNotify(context, writer); - break; - case "notifyAll": - generateNotifyAll(context, writer); - break; - } - } - - @Override - public void generate(InjectorContext context, MethodReference methodRef) throws IOException { - switch (methodRef.getName()) { - case "getClass": - generateGetClass(context); - break; - case "wrap": - generateWrap(context); - break; - } - } - - @Override - public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) { - switch (method.getReference().getName()) { - case "clone": - method.getVariable(0).connect(method.getResult()); - break; - case "getClass": - achieveGetClass(agent, method); - break; - case "wrap": - method.getVariable(1).connect(method.getResult()); - break; - //case "wait": - // method.getVariable(0).connect(method.getResult()); - // break; - - } - } - - private void generateInit(GeneratorContext context, SourceWriter writer) throws IOException { - writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").softNewLine(); - } - - private void generateGetClass(InjectorContext context) throws IOException { - SourceWriter writer = context.getWriter(); - writer.append("$rt_cls("); - context.writeExpr(context.getArgument(0)); - writer.append(".constructor)"); - } - - private void achieveGetClass(DependencyAgent agent, MethodDependency method) { - MethodReference initMethod = new MethodReference(Class.class, "createNew", Class.class); - agent.linkMethod(initMethod, null).use(); - method.getResult().propagate(agent.getType("java.lang.Class")); - } - - private void generateHashCode(GeneratorContext context, SourceWriter writer) throws IOException { - writer.append("return ").append(context.getParameterName(0)).append(".$id;").softNewLine(); - } - - private void generateClone(GeneratorContext context, SourceWriter writer) throws IOException { - String obj = context.getParameterName(0); - writer.append("var copy = new ").append(obj).append(".constructor();").softNewLine(); - writer.append("for (var field in " + obj + ") {").softNewLine().indent(); - writer.append("if (!" + obj + ".hasOwnProperty(field)) {").softNewLine().indent(); - writer.append("continue;").softNewLine().outdent().append("}").softNewLine(); - writer.append("copy[field] = " + obj + "[field];").softNewLine().outdent().append("}").softNewLine(); - writer.append("return copy;").softNewLine(); - } - - private void generateWrap(InjectorContext context) throws IOException { - context.writeExpr(context.getArgument(0)); - } - - private void generateWait(GeneratorContext context, SourceWriter writer) throws IOException { - String pname = context.getParameterName(1); - String obj = context.getParameterName(0); - writer.append("(function(){").indent().softNewLine(); - writer.append("var completed = false;").softNewLine(); - writer.append("var retCallback = ").append(context.getCompleteContinuation()).append(";").softNewLine(); - writer.append("var callback = function(){").indent().softNewLine(); - writer.append("if (completed){return;} completed=true;").softNewLine(); - writer.append("retCallback($rt_asyncResult(null));").softNewLine(); - writer.outdent().append("};").softNewLine(); - writer.append("if (").append(pname).append(">0){").indent().softNewLine(); - writer.append("$rt_setTimeout(callback, ").append(pname).append(");").softNewLine(); - writer.outdent().append("}").softNewLine(); - addNotifyListener(context, writer, "callback"); - writer.outdent().append("})();").softNewLine(); - - - - } - - private void generateNotify(GeneratorContext context, SourceWriter writer) throws IOException { - sendNotify(context, writer); - } - - private void generateNotifyAll(GeneratorContext context, SourceWriter writer) throws IOException { - sendNotifyAll(context, writer); - } - - private String getNotifyListeners(GeneratorContext context){ - return context.getParameterName(0)+".__notifyListeners"; - } - - private void addNotifyListener(GeneratorContext context, SourceWriter writer, String callback) throws IOException { - String lArr = getNotifyListeners(context); - writer.append(lArr).append("=").append(lArr).append("||[];").softNewLine(); - writer.append(lArr).append(".push(").append(callback).append(");").softNewLine(); - } - - private void sendNotify(GeneratorContext context, SourceWriter writer) throws IOException { - String lArr = getNotifyListeners(context); - writer.append("$rt_setTimeout(function(){").indent().softNewLine(); - writer.append("if (!").append(lArr).append(" || ").append(lArr).append(".length===0){return;}").softNewLine(); - writer.append(lArr).append(".shift().apply(null);").softNewLine(); - writer.outdent().append("}, 0);").softNewLine(); - } - - private void sendNotifyAll(GeneratorContext context, SourceWriter writer) throws IOException { - String obj = context.getParameterName(0); - String lArr = getNotifyListeners(context); - writer.append("$rt_setTimeout(function(){").indent().softNewLine(); - writer.append("if (!").append(lArr).append("){return;}").softNewLine(); - writer.append("while (").append(lArr).append(".length>0){").indent().softNewLine(); - writer.append(lArr).append(".shift().call(null);").softNewLine(); - writer.outdent().append("}"); - writer.outdent().append("}, 0);").softNewLine(); - - } - -} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/StringNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/StringNativeGenerator.java deleted file mode 100644 index c2bb09b26..000000000 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/StringNativeGenerator.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2013 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.java.lang; - -import java.io.IOException; -import org.teavm.dependency.DependencyAgent; -import org.teavm.dependency.DependencyPlugin; -import org.teavm.dependency.MethodDependency; -import org.teavm.javascript.ni.Injector; -import org.teavm.javascript.ni.InjectorContext; -import org.teavm.model.CallLocation; -import org.teavm.model.MethodReference; - -/** - * - * @author Alexey Andreev - */ -public class StringNativeGenerator implements Injector, DependencyPlugin { - @Override - public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) { - switch (method.getReference().getName()) { - case "wrap": - method.getVariable(1).connect(method.getResult()); - break; - } - } - - @Override - public void generate(InjectorContext context, MethodReference methodRef) throws IOException { - switch (methodRef.getName()) { - case "wrap": - context.writeExpr(context.getArgument(0)); - break; - } - } -} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java index 0bbe21f42..65bb9ba6e 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java @@ -18,8 +18,8 @@ package org.teavm.classlib.java.lang; import java.io.IOException; import org.teavm.codegen.SourceWriter; import org.teavm.dependency.*; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.CallLocation; import org.teavm.model.FieldReference; import org.teavm.model.MethodReference; @@ -48,9 +48,6 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin { .appendField(new FieldReference("java.lang.System", "err")) .ws().append('=').ws().append(context.getParameterName(1)).append(";").softNewLine(); break; - case "identityHashCode": - writer.append("return ").append(context.getParameterName(1)).append(".$id;").softNewLine(); - break; } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TBoolean.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TBoolean.java index afe614825..14c3772c9 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TBoolean.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TBoolean.java @@ -16,7 +16,6 @@ package org.teavm.classlib.java.lang; import org.teavm.classlib.java.io.TSerializable; -import org.teavm.javascript.ni.GeneratedBy; /** * @@ -80,7 +79,6 @@ public class TBoolean extends TObject implements TSerializable, TComparable { return UTF16Helper.lowSurrogate(codePoint); } - // TODO: implement toLowerCase/toUpperCase/toTitleCase using UnicodeData.txt instead of built-in JS - @GeneratedBy(CharacterNativeGenerator.class) - public static native char toLowerCase(char ch); + public static char toLowerCase(char ch) { + return (char)toLowerCase((int)ch); + } - @GeneratedBy(CharacterNativeGenerator.class) - public static native int toLowerCase(int ch); + public static int toLowerCase(int ch) { + return Platform.stringFromCharCode(ch).toLowerCase().charCodeAt(0); + } - @GeneratedBy(CharacterNativeGenerator.class) - public static native char toUpperCase(char ch); + public static char toUpperCase(char ch) { + return (char)toUpperCase((int)ch); + } - @GeneratedBy(CharacterNativeGenerator.class) - public static native int toUpperCase(int codePoint); + public static int toUpperCase(int codePoint) { + return Platform.stringFromCharCode(codePoint).toUpperCase().charCodeAt(0); + } public static int digit(char ch, int radix) { return digit((int)ch, radix); @@ -286,25 +290,23 @@ public class TCharacter extends TObject implements TComparable { private static int[] getDigitMapping() { if (digitMapping == null) { - digitMapping = UnicodeHelper.decodeIntByte(obtainDigitMapping()); + digitMapping = UnicodeHelper.decodeIntByte(obtainDigitMapping().getValue()); } return digitMapping; } - @GeneratedBy(CharacterNativeGenerator.class) - @PluggableDependency(CharacterNativeGenerator.class) - private static native String obtainDigitMapping(); + @MetadataProvider(CharacterMetadataGenerator.class) + private static native StringResource obtainDigitMapping(); private static UnicodeHelper.Range[] getClasses() { if (classMapping == null) { - classMapping = UnicodeHelper.extractRle(obtainClasses()); + classMapping = UnicodeHelper.extractRle(obtainClasses().getValue()); } return classMapping; } - @GeneratedBy(CharacterNativeGenerator.class) - @PluggableDependency(CharacterNativeGenerator.class) - private static native String obtainClasses(); + @MetadataProvider(CharacterMetadataGenerator.class) + private static native StringResource obtainClasses(); public static int toChars(int codePoint, char[] dst, int dstIndex) { if (codePoint >= UTF16Helper.SUPPLEMENTARY_PLANE) { diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java index 94152045c..642a28069 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java @@ -15,9 +15,11 @@ */ package org.teavm.classlib.java.lang; -import org.teavm.dependency.PluggableDependency; -import org.teavm.javascript.ni.GeneratedBy; -import org.teavm.javascript.ni.InjectedBy; +import org.teavm.classlib.impl.DeclaringClassMetadataGenerator; +import org.teavm.platform.Platform; +import org.teavm.platform.PlatformClass; +import org.teavm.platform.metadata.ClassResource; +import org.teavm.platform.metadata.ClassScopedMetadataProvider; /** * @@ -25,113 +27,130 @@ import org.teavm.javascript.ni.InjectedBy; */ public class TClass extends TObject { TString name; - TString binaryName; - boolean primitive; - boolean array; - boolean isEnum; private TClass componentType; private boolean componentTypeDirty = true; + private PlatformClass platformClass; - static TClass createNew() { - return new TClass<>(); + private TClass(PlatformClass platformClass) { + this.platformClass = platformClass; + platformClass.setJavaClass(Platform.getPlatformObject(this)); } - @InjectedBy(ClassNativeGenerator.class) - public native boolean isInstance(TObject obj); + public static TClass getClass(PlatformClass cls) { + if (cls == null) { + return null; + } + TClass result = (TClass)(Object)Platform.asJavaClass(cls.getJavaClass()); + if (result == null) { + result = new TClass<>(cls); + } + return result; + } - @InjectedBy(ClassNativeGenerator.class) - public native boolean isAssignableFrom(TClass obj); + public PlatformClass getPlatformClass() { + return platformClass; + } + + public boolean isInstance(TObject obj) { + return Platform.isInstance(Platform.getPlatformObject(obj), platformClass); + } + + public boolean isAssignableFrom(TClass obj) { + return Platform.isAssignable(obj.getPlatformClass(), platformClass); + } - @PluggableDependency(ClassNativeGenerator.class) public TString getName() { + if (name == null) { + name = TString.wrap(platformClass.getMetadata().getName()); + } return name; } public boolean isPrimitive() { - return primitive; + return platformClass.getMetadata().isPrimitive(); } public boolean isArray() { - return array; + return platformClass.getMetadata().getArrayItem() != null; } public boolean isEnum() { - return isEnum; + return platformClass.getMetadata().isEnum(); } public TClass getComponentType() { if (componentTypeDirty) { - componentType = getComponentType0(); + PlatformClass arrayItem = platformClass.getMetadata().getArrayItem(); + componentType = arrayItem != null ? getClass(arrayItem) : null; componentTypeDirty = false; } return componentType; } - @GeneratedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - private native TClass getComponentType0(); + @SuppressWarnings("unchecked") + static TClass voidClass() { + return (TClass)getClass(Platform.getPrimitives().getVoidClass()); + } - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass voidClass(); + @SuppressWarnings("unchecked") + static TClass booleanClass() { + return (TClass)getClass(Platform.getPrimitives().getBooleanClass()); + } - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass booleanClass(); + @SuppressWarnings("unchecked") + static TClass charClass() { + return (TClass)getClass(Platform.getPrimitives().getCharClass()); + } - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass charClass(); + @SuppressWarnings("unchecked") + static TClass byteClass() { + return (TClass)getClass(Platform.getPrimitives().getByteClass()); + } - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass byteClass(); + @SuppressWarnings("unchecked") + static TClass shortClass() { + return (TClass)getClass(Platform.getPrimitives().getShortClass()); + } - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass shortClass(); + @SuppressWarnings("unchecked") + static TClass intClass() { + return (TClass)getClass(Platform.getPrimitives().getIntClass()); + } - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass intClass(); + @SuppressWarnings("unchecked") + static TClass longClass() { + return (TClass)getClass(Platform.getPrimitives().getLongClass()); + } - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass longClass(); + @SuppressWarnings("unchecked") + static TClass floatClass() { + return (TClass)getClass(Platform.getPrimitives().getFloatClass()); + } - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass floatClass(); - - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - static native TClass doubleClass(); - - @InjectedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - public static native TClass wrapClass(Class cls); + @SuppressWarnings("unchecked") + static TClass doubleClass() { + return (TClass)getClass(Platform.getPrimitives().getDoubleClass()); + } public boolean desiredAssertionStatus() { return true; } - @GeneratedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - public native TClass getSuperclass(); - - public T[] getEnumConstants() { - return isEnum ? getEnumConstantsImpl() : null; + @SuppressWarnings("unchecked") + public TClass getSuperclass() { + return (TClass)getClass(platformClass.getMetadata().getSuperclass()); } - @InjectedBy(ClassNativeGenerator.class) - public native T[] getEnumConstantsImpl(); + @SuppressWarnings("unchecked") + public T[] getEnumConstants() { + return isEnum() ? (T[])Platform.getEnumConstants(platformClass) : null; + } @SuppressWarnings("unchecked") public T cast(TObject obj) { - if (obj != null && !isAssignableFrom(TClass.wrapClass(obj.getClass()))) { - throw new TClassCastException(TString.wrap(new TStringBuilder() - .append(TClass.wrapClass(obj.getClass()).getName()) - .append(TString.wrap(" is not subtype of ")).append(name).toString())); + if (obj != null && !isAssignableFrom((TClass)(Object)obj.getClass())) { + throw new TClassCastException(TString.wrap(obj.getClass().getName() + + " is not subtype of " + name)); } return (T)obj; } @@ -140,31 +159,36 @@ public class TClass extends TObject { return TClassLoader.getSystemClassLoader(); } - @GeneratedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - private static native TClass forNameImpl(TString name); - public static TClass forName(TString name) throws TClassNotFoundException { - TClass result = forNameImpl(name); - if (result == null) { + PlatformClass cls = Platform.lookupClass(name.toString()); + if (cls == null) { throw new TClassNotFoundException(); } - return result; + return getClass(cls); } @SuppressWarnings("unused") public static TClass forName(TString name, boolean initialize, TClassLoader loader) - throws TClassNotFoundException { + throws TClassNotFoundException { return forName(name); } - @GeneratedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - public native T newInstance() throws TInstantiationException, TIllegalAccessException; + @SuppressWarnings("unchecked") + public T newInstance() throws TInstantiationException, TIllegalAccessException { + Object instance = Platform.newInstance(platformClass); + if (instance == null) { + throw new TInstantiationException(); + } + return (T)instance; + } - @GeneratedBy(ClassNativeGenerator.class) - @PluggableDependency(ClassNativeGenerator.class) - public native TClass getDeclaringClass(); + public TClass getDeclaringClass() { + ClassResource res = getDeclaringClass(platformClass); + return res != null ? getClass(Platform.classFromResource(res)) : null; + } + + @ClassScopedMetadataProvider(DeclaringClassMetadataGenerator.class) + private static native ClassResource getDeclaringClass(PlatformClass cls); @SuppressWarnings("unchecked") public TClass asSubclass(TClass clazz) { diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStream_stderr.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStream_stderr.java index da0d23007..09038fd60 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStream_stderr.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStream_stderr.java @@ -17,7 +17,7 @@ package org.teavm.classlib.java.lang; import org.teavm.classlib.java.io.TIOException; import org.teavm.classlib.java.io.TOutputStream; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.platform.Platform; /** * @@ -25,6 +25,7 @@ import org.teavm.javascript.ni.GeneratedBy; */ class TConsoleOutputStream_stderr extends TOutputStream { @Override - @GeneratedBy(ConsoleOutputStreamGenerator.class) - public native void write(int b) throws TIOException; + public void write(int b) throws TIOException { + Platform.getConsole().error(b); + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStream_stdout.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStream_stdout.java index df027892f..4c816bfb4 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStream_stdout.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStream_stdout.java @@ -17,7 +17,7 @@ package org.teavm.classlib.java.lang; import org.teavm.classlib.java.io.TIOException; import org.teavm.classlib.java.io.TOutputStream; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.platform.Platform; /** * @@ -25,6 +25,7 @@ import org.teavm.javascript.ni.GeneratedBy; */ class TConsoleOutputStream_stdout extends TOutputStream { @Override - @GeneratedBy(ConsoleOutputStreamGenerator.class) - public native void write(int b) throws TIOException; + public void write(int b) throws TIOException { + Platform.getConsole().output(b); + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java index eb085acf8..7e1205acd 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java @@ -15,8 +15,8 @@ */ package org.teavm.classlib.java.lang; -import org.teavm.javascript.ni.GeneratedBy; -import org.teavm.javascript.ni.InjectedBy; +import org.teavm.javascript.spi.GeneratedBy; +import org.teavm.javascript.spi.InjectedBy; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TEnum.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TEnum.java index 38d8ca2c6..cc02cc5d7 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TEnum.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TEnum.java @@ -16,7 +16,7 @@ package org.teavm.classlib.java.lang; import org.teavm.classlib.java.io.TSerializable; -import org.teavm.javascript.ni.Rename; +import org.teavm.javascript.spi.Rename; /** * @@ -61,7 +61,7 @@ public abstract class TEnum> extends TObject implements TComp @SuppressWarnings("unchecked") public final TClass getDeclaringClass() { - return (TClass)TClass.wrapClass(getClass()); + return (TClass)(Object)getClass(); } @Override diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java index 2a6181ca7..916dcc159 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java @@ -15,7 +15,7 @@ */ package org.teavm.classlib.java.lang; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java index 5c3f71e8c..81d57c910 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TLong.java @@ -15,7 +15,7 @@ */ package org.teavm.classlib.java.lang; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java index a74a6574c..016b67253 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java @@ -15,7 +15,7 @@ */ package org.teavm.classlib.java.lang; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java index 9ca2ef4e4..d289eb974 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java @@ -15,6 +15,7 @@ */ package org.teavm.classlib.java.lang; +<<<<<<< HEAD import org.teavm.dependency.PluggableDependency; import org.teavm.javascript.ni.GeneratedBy; @@ -22,6 +23,11 @@ import org.teavm.javascript.ni.InjectedBy; import org.teavm.javascript.ni.Rename; import org.teavm.javascript.ni.Superclass; import org.teavm.runtime.Async; +======= +import org.teavm.javascript.spi.Rename; +import org.teavm.javascript.spi.Superclass; +import org.teavm.platform.Platform; +>>>>>>> dd25ae4759716d735fe6f93a54c8bfab2e7fc7bf /** * @@ -69,18 +75,20 @@ public class TObject { public TObject() { } - @GeneratedBy(ObjectNativeGenerator.class) @Rename("") - private native void init(); + private void init() { + Platform.getPlatformObject(this).setId(Platform.nextObjectId()); + } - @InjectedBy(ObjectNativeGenerator.class) @Rename("getClass") - @PluggableDependency(ObjectNativeGenerator.class) - public native final TClass getClass0(); + public final TClass getClass0() { + return TClass.getClass(Platform.getPlatformObject(this).getPlatformClass()); + } @Override - @GeneratedBy(ObjectNativeGenerator.class) - public native int hashCode(); + public int hashCode() { + return identity(); + } @Rename("equals") public boolean equals0(TObject other) { @@ -92,13 +100,19 @@ public class TObject { return getClass().getName() + "@" + TInteger.toHexString(identity()); } - @GeneratedBy(ObjectNativeGenerator.class) - native int identity(); + int identity() { + return Platform.getPlatformObject(this).getId(); + } - @GeneratedBy(ObjectNativeGenerator.class) - @PluggableDependency(ObjectNativeGenerator.class) @Override - protected native Object clone() throws TCloneNotSupportedException; + protected Object clone() throws TCloneNotSupportedException { + if (!(this instanceof TCloneable) && Platform.getPlatformObject(this) + .getPlatformClass().getMetadata().getArrayItem() == null) { + throw new TCloneNotSupportedException(); + } + Platform.getPlatformObject(this).setId(Platform.nextObjectId()); + return Platform.clone(this); + } @GeneratedBy(ObjectNativeGenerator.class) @Rename("notify") @@ -137,7 +151,7 @@ public class TObject { protected void finalize() throws TThrowable { } - @InjectedBy(ObjectNativeGenerator.class) - @PluggableDependency(ObjectNativeGenerator.class) - public static native TObject wrap(Object obj); + public static TObject wrap(Object obj) { + return (TObject)obj; + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TRuntimeException.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TRuntimeException.java index 789487406..80a106bc9 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TRuntimeException.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TRuntimeException.java @@ -15,7 +15,7 @@ */ package org.teavm.classlib.java.lang; -import org.teavm.javascript.ni.Superclass; +import org.teavm.javascript.spi.Superclass; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TString.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TString.java index 9d309e31e..a5ba75b2c 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TString.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TString.java @@ -23,8 +23,6 @@ import org.teavm.classlib.java.util.TComparator; import org.teavm.classlib.java.util.THashMap; import org.teavm.classlib.java.util.TMap; import org.teavm.classlib.java.util.regex.TPattern; -import org.teavm.dependency.PluggableDependency; -import org.teavm.javascript.ni.InjectedBy; /** * @@ -592,9 +590,9 @@ public class TString extends TObject implements TSerializable, TComparable>>>>>> dd25ae4759716d735fe6f93a54c8bfab2e7fc7bf /** * * @author Alexey Andreev */ public class TThread extends TObject implements TRunnable { +<<<<<<< HEAD private static TThread mainThread = new TThread(TString.wrap("main")); private static TThread currentThread = mainThread; private static long nextId = 1; private static int activeCount = 1; private long id; +======= + private static Window window = (Window)JS.getGlobal(); + private static TThread currentThread = new TThread(TString.wrap("main")); +>>>>>>> dd25ae4759716d735fe6f93a54c8bfab2e7fc7bf private TString name; private TRunnable target; @@ -90,9 +103,16 @@ public class TThread extends TObject implements TRunnable { } @Async - @GeneratedBy(ThreadNativeGenerator.class) public static native void yield(); + private static void yield(final AsyncCallback callback) { + window.setTimeout(new TimerHandler() { + @Override public void onTimer() { + callback.complete(null); + } + }, 0); + } + public void interrupt() { } @@ -116,13 +136,21 @@ public class TThread extends TObject implements TRunnable { return TObject.holdsLock(obj); } - public static void sleep(long millis) throws TInterruptedException { - sleep((double)millis); - } - @Async +<<<<<<< HEAD @GeneratedBy(ThreadNativeGenerator.class) private static native void sleep(double millis) throws TInterruptedException; +======= + public static native void sleep(long millis) throws TInterruptedException; + + private static void sleep(long millis, final AsyncCallback callback) { + window.setTimeout(new TimerHandler() { + @Override public void onTimer() { + callback.complete(null); + } + }, millis); + } +>>>>>>> dd25ae4759716d735fe6f93a54c8bfab2e7fc7bf } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java index 8a01cdb37..b0350ac7f 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java @@ -17,9 +17,9 @@ package org.teavm.classlib.java.lang; import org.teavm.classlib.java.io.TPrintStream; import org.teavm.classlib.java.util.TArrays; -import org.teavm.javascript.ni.Remove; -import org.teavm.javascript.ni.Rename; -import org.teavm.javascript.ni.Superclass; +import org.teavm.javascript.spi.Remove; +import org.teavm.javascript.spi.Rename; +import org.teavm.javascript.spi.Superclass; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ThreadNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ThreadNativeGenerator.java deleted file mode 100644 index 5af53318f..000000000 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/ThreadNativeGenerator.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2015 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.java.lang; - -import java.io.IOException; -import org.teavm.codegen.SourceWriter; -import org.teavm.dependency.DependencyAgent; -import org.teavm.dependency.DependencyPlugin; -import org.teavm.dependency.MethodDependency; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; -import org.teavm.model.CallLocation; -import org.teavm.model.MethodReference; - -/** - * - * @author Alexey Andreev - */ -public class ThreadNativeGenerator implements Generator, DependencyPlugin { - - private static final MethodReference launchRef = new MethodReference(Thread.class, - "launch", Thread.class, void.class); - - @Override - public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { - if (methodRef.getName().equals("sleep")) { - generateSleep(context, writer); - } else if (methodRef.getName().equals("yield")) { - generateYield(context, writer); - } else if ( methodRef.getName().equals("start")){ - generateStart(context, writer); - } - } - - @Override - public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) { - switch (method.getReference().getName()) { - case "start": { - MethodDependency performMethod = agent.linkMethod(launchRef, null); - method.getVariable(0).connect(performMethod.getVariable(1)); - performMethod.use(); - break; - } - } - } - - private void generateSleep(GeneratorContext context, SourceWriter writer) throws IOException { - writer.append("$rt_setTimeout(function() {").indent().softNewLine(); - writer.append(context.getCompleteContinuation()).append("($rt_asyncResult(null));").softNewLine(); - writer.outdent().append("},").ws().append(context.getParameterName(1)).append(");").softNewLine(); - } - - private void generateYield(GeneratorContext context, SourceWriter writer) throws IOException { - writer.append("$rt_setTimeout(function() {").indent().softNewLine(); - writer.append(context.getCompleteContinuation()).append("($rt_asyncResult(null));").softNewLine(); - writer.outdent().append("},").ws().append("0);").softNewLine(); - } - - private void generateStart(GeneratorContext context, SourceWriter writer) throws IOException { - String obj = context.getParameterName(0); - writer.append("$rt_setTimeout(function() { $rt_rootInvocationAdapter(").appendMethodBody(launchRef).append(")(") - .append(obj).append(");},0);").softNewLine(); - } -} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/ArrayNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/ArrayNativeGenerator.java index 0f043c3ab..468334f63 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/ArrayNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/ArrayNativeGenerator.java @@ -18,8 +18,8 @@ package org.teavm.classlib.java.lang.reflect; import java.io.IOException; import org.teavm.codegen.SourceWriter; import org.teavm.dependency.*; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.CallLocation; import org.teavm.model.ClassReader; import org.teavm.model.MethodDescriptor; @@ -93,15 +93,14 @@ public class ArrayNativeGenerator implements Generator, DependencyPlugin { private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException { String type = context.getParameterName(1); String length = context.getParameterName(2); - writer.append("var cls = " + type + ".$data;").softNewLine(); - writer.append("if (cls.primitive) {").softNewLine().indent(); + writer.append("if (").append(type).append(".$meta.primitive) {").softNewLine().indent(); for (String primitive : primitives) { - writer.append("if (cls == $rt_" + primitive.toLowerCase() + "cls()) {").indent().softNewLine(); + writer.append("if (" + type + " == $rt_" + primitive.toLowerCase() + "cls()) {").indent().softNewLine(); writer.append("return $rt_create" + primitive + "Array(" + length + ");").softNewLine(); writer.outdent().append("}").softNewLine(); } writer.outdent().append("} else {").indent().softNewLine(); - writer.append("return $rt_createArray(cls, " + length + ")").softNewLine(); + writer.append("return $rt_createArray(" + type + ", " + length + ")").softNewLine(); writer.outdent().append("}").softNewLine(); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/TArray.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/TArray.java index 9c3177aae..0f46fbf0f 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/TArray.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/TArray.java @@ -17,7 +17,8 @@ package org.teavm.classlib.java.lang.reflect; import org.teavm.classlib.java.lang.*; import org.teavm.dependency.PluggableDependency; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; +import org.teavm.platform.PlatformClass; /** * @@ -38,12 +39,12 @@ public final class TArray extends TObject { if (length < 0) { throw new TNegativeArraySizeException(); } - return newInstanceImpl(componentType, length); + return newInstanceImpl(componentType.getPlatformClass(), length); } @GeneratedBy(ArrayNativeGenerator.class) @PluggableDependency(ArrayNativeGenerator.class) - private static native TObject newInstanceImpl(TClass componentType, int length); + private static native TObject newInstanceImpl(PlatformClass componentType, int length); public static TObject get(TObject array, int index) throws TIllegalArgumentException, TArrayIndexOutOfBoundsException { diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/net/TURISyntaxException.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/net/TURISyntaxException.java index c6ef0a80b..1a688563b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/net/TURISyntaxException.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/net/TURISyntaxException.java @@ -21,7 +21,7 @@ import org.teavm.classlib.java.lang.TException; import org.teavm.classlib.java.lang.TIllegalArgumentException; import org.teavm.classlib.java.lang.TNullPointerException; import org.teavm.classlib.java.lang.TString; -import org.teavm.javascript.ni.Rename; +import org.teavm.javascript.spi.Rename; /** * A {@code URISyntaxException} will be thrown if some information could not be parsed diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/DateNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/DateNativeGenerator.java index 24488481e..7b49f1b21 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/DateNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/DateNativeGenerator.java @@ -20,8 +20,8 @@ import org.teavm.codegen.SourceWriter; import org.teavm.dependency.DependencyAgent; import org.teavm.dependency.DependencyPlugin; import org.teavm.dependency.MethodDependency; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.CallLocation; import org.teavm.model.MethodReference; diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/RandomNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/RandomNativeGenerator.java index c922cf767..4fc673db8 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/RandomNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/RandomNativeGenerator.java @@ -17,8 +17,8 @@ package org.teavm.classlib.java.util; import java.io.IOException; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.MethodReference; /** diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractList.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractList.java index d012d7c51..c7b2b4459 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractList.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TAbstractList.java @@ -16,7 +16,7 @@ package org.teavm.classlib.java.util; import org.teavm.classlib.java.lang.*; -import org.teavm.javascript.ni.Rename; +import org.teavm.javascript.spi.Rename; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrayList.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrayList.java index c411b0f18..43a998c44 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrayList.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrayList.java @@ -18,7 +18,7 @@ package org.teavm.classlib.java.util; import java.util.Arrays; import org.teavm.classlib.java.io.TSerializable; import org.teavm.classlib.java.lang.*; -import org.teavm.javascript.ni.Rename; +import org.teavm.javascript.spi.Rename; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TBitSet.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TBitSet.java index 77eebde48..bafc551b2 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TBitSet.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TBitSet.java @@ -17,7 +17,7 @@ package org.teavm.classlib.java.util; import org.teavm.classlib.java.io.TSerializable; import org.teavm.classlib.java.lang.*; -import org.teavm.javascript.ni.Rename; +import org.teavm.javascript.spi.Rename; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TDate.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TDate.java index 1fae8ebc0..5d14d375b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TDate.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TDate.java @@ -18,7 +18,7 @@ package org.teavm.classlib.java.util; import org.teavm.classlib.java.lang.TComparable; import org.teavm.classlib.java.lang.TSystem; import org.teavm.dependency.PluggableDependency; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/THashMap.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/THashMap.java index 16890395f..4c2b2973d 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/THashMap.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/THashMap.java @@ -39,7 +39,7 @@ import org.teavm.classlib.java.lang.TCloneNotSupportedException; import org.teavm.classlib.java.lang.TIllegalArgumentException; import org.teavm.classlib.java.lang.TIllegalStateException; import org.teavm.classlib.java.lang.TObject; -import org.teavm.javascript.ni.Rename; +import org.teavm.javascript.spi.Rename; public class THashMap extends TAbstractMap implements TSerializable { transient int elementCount; diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/THashSet.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/THashSet.java index e87bf7f42..eff1c5a1e 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/THashSet.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/THashSet.java @@ -20,7 +20,7 @@ import org.teavm.classlib.java.io.TSerializable; import org.teavm.classlib.java.lang.TCloneNotSupportedException; import org.teavm.classlib.java.lang.TCloneable; import org.teavm.classlib.java.lang.TObject; -import org.teavm.javascript.ni.Rename; +import org.teavm.javascript.spi.Rename; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java index 5d71eed1c..864e1270e 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java @@ -18,7 +18,7 @@ package org.teavm.classlib.java.util; import org.teavm.classlib.java.io.TSerializable; import org.teavm.classlib.java.lang.TMath; import org.teavm.classlib.java.lang.TObject; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TServiceLoader.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TServiceLoader.java index 6299fed4c..035066dde 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TServiceLoader.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TServiceLoader.java @@ -16,6 +16,7 @@ package org.teavm.classlib.java.util; import org.teavm.classlib.java.lang.*; +import org.teavm.platform.PlatformClass; /** * @@ -48,7 +49,7 @@ public final class TServiceLoader extends TObject implements TIterable { } public static TServiceLoader load(TClass service) { - return new TServiceLoader<>(loadServices(service)); + return new TServiceLoader<>(loadServices(service.getPlatformClass())); } public static TServiceLoader load(TClass service, @SuppressWarnings("unused") TClassLoader loader) { @@ -59,7 +60,7 @@ public final class TServiceLoader extends TObject implements TIterable { return load(service); } - private static native T[] loadServices(TClass serviceType); + private static native T[] loadServices(PlatformClass cls); public void reload() { // Do nothing, services are bound at build time diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java index 4585cec6a..9b1d12049 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TTimer.java @@ -19,7 +19,7 @@ import org.teavm.classlib.java.lang.TIllegalStateException; import org.teavm.classlib.java.lang.TObject; import org.teavm.classlib.java.lang.TString; import org.teavm.dependency.PluggableDependency; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; /** * diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java index 08ea7f48c..3a376cd1d 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TimerNativeGenerator.java @@ -21,8 +21,8 @@ import org.teavm.codegen.SourceWriter; import org.teavm.dependency.DependencyAgent; import org.teavm.dependency.DependencyPlugin; import org.teavm.dependency.MethodDependency; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.CallLocation; import org.teavm.model.MethodReference; diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java index 0259c4893..7657adfac 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/LoggerNativeGenerator.java @@ -17,8 +17,8 @@ package org.teavm.classlib.java.util.logging; import java.io.IOException; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.MethodReference; /** diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java index 60cd62901..1f42153a8 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/logging/TLogger.java @@ -18,7 +18,7 @@ package org.teavm.classlib.java.util.logging; import org.teavm.classlib.java.lang.*; import org.teavm.classlib.java.util.THashMap; import org.teavm.classlib.java.util.TMap; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; /** * 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/codegen/SourceWriter.java b/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java index 5e2749cb4..a1ced11f0 100644 --- a/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java +++ b/teavm-core/src/main/java/org/teavm/codegen/SourceWriter.java @@ -103,6 +103,10 @@ public class SourceWriter implements Appendable, LocationProvider { return append(naming.getNameFor(cls)); } + public SourceWriter appendClass(Class cls) throws NamingException, IOException { + return append(naming.getNameFor(cls.getName())); + } + public SourceWriter appendField(FieldReference field) throws NamingException, IOException { return append(naming.getNameFor(field)); } @@ -113,7 +117,12 @@ public class SourceWriter implements Appendable, LocationProvider { public SourceWriter appendMethod(String className, String name, ValueType... params) throws NamingException, IOException { - return append(naming.getNameFor(new MethodReference(className, new MethodDescriptor(name, params)))); + return append(naming.getNameFor(new MethodReference(className, name, params))); + } + + public SourceWriter appendMethod(Class cls, String name, Class... params) + throws NamingException, IOException { + return append(naming.getNameFor(new MethodReference(cls, name, params))); } public SourceWriter appendMethodBody(MethodReference method) throws NamingException, IOException { @@ -125,6 +134,11 @@ public class SourceWriter implements Appendable, LocationProvider { return append(naming.getFullNameFor(new MethodReference(className, new MethodDescriptor(name, params)))); } + public SourceWriter appendMethodBody(Class cls, String name, Class... params) + throws NamingException, IOException { + return append(naming.getFullNameFor(new MethodReference(cls, name, params))); + } + private void appendIndent() throws IOException { if (minified) { return; diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyPlugin.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyPlugin.java index 63d44035d..8061ceb58 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyPlugin.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyPlugin.java @@ -22,5 +22,5 @@ import org.teavm.model.CallLocation; * @author Alexey Andreev */ public interface DependencyPlugin { - void methodAchieved(DependencyAgent checker, MethodDependency method, CallLocation location); + void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location); } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java index 477eccc0f..e74a06ea6 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java @@ -18,10 +18,10 @@ package org.teavm.javascript; import java.util.*; import org.teavm.common.*; import org.teavm.javascript.ast.*; -import org.teavm.javascript.ni.GeneratedBy; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.InjectedBy; -import org.teavm.javascript.ni.PreserveOriginalName; +import org.teavm.javascript.spi.GeneratedBy; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.InjectedBy; +import org.teavm.javascript.spi.PreserveOriginalName; import org.teavm.model.*; import org.teavm.model.util.AsyncProgramSplitter; import org.teavm.model.util.ProgramUtils; 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 e1e24e13f..594c41ce6 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -26,11 +26,12 @@ import org.teavm.common.ServiceRepository; import org.teavm.debugging.information.DebugInformationEmitter; import org.teavm.debugging.information.DeferredCallSite; import org.teavm.debugging.information.DummyDebugInformationEmitter; +import org.teavm.diagnostics.Diagnostics; import org.teavm.javascript.ast.*; -import org.teavm.javascript.ni.GeneratorContext; -import org.teavm.javascript.ni.InjectedBy; -import org.teavm.javascript.ni.Injector; -import org.teavm.javascript.ni.InjectorContext; +import org.teavm.javascript.spi.GeneratorContext; +import org.teavm.javascript.spi.InjectedBy; +import org.teavm.javascript.spi.Injector; +import org.teavm.javascript.spi.InjectorContext; import org.teavm.model.*; /** @@ -53,6 +54,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext private Deque locationStack = new ArrayDeque<>(); private DeferredCallSite lastCallSite; private DeferredCallSite prevCallSite; + private Set asyncMethods; + private Set asyncFamilyMethods; + private Diagnostics diagnostics; private boolean async; @Override @@ -110,12 +114,16 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } public Renderer(SourceWriter writer, ListableClassHolderSource classSource, ClassLoader classLoader, - ServiceRepository services) { + ServiceRepository services, Set asyncMethods, Set asyncFamilyMethods, + Diagnostics diagnostics) { this.naming = writer.getNaming(); this.writer = writer; this.classSource = classSource; this.classLoader = classLoader; this.services = services; + this.asyncMethods = new HashSet<>(asyncMethods); + this.asyncFamilyMethods = new HashSet<>(asyncFamilyMethods); + this.diagnostics = diagnostics; } @Override @@ -199,43 +207,11 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } private void renderRuntimeCls() throws IOException { - writer.append("function $rt_cls").ws().append("(clsProto)").ws().append("{") - .indent().softNewLine(); - String classClass = "java.lang.Class"; - writer.append("var cls").ws().append("=").ws().append("clsProto.classObject;").softNewLine(); - writer.append("if").ws().append("(typeof cls").ws().append("===").ws().append("'undefined')").ws() - .append("{").softNewLine().indent(); - MethodReference createMethodRef = new MethodReference(classClass, "createNew", ValueType.object(classClass)); - writer.append("cls").ws().append("=").ws().appendMethodBody(createMethodRef).append("();").softNewLine(); - writer.append("cls.$data = clsProto;").softNewLine(); - if (classSource.get(classClass).getField("name") != null) { - writer.append("cls.").appendField(new FieldReference(classClass, "name")).ws().append("=").ws() - .append("clsProto.$meta.name").ws().append("!==").ws().append("undefined").ws().append("?").ws() - .append("$rt_str(clsProto.$meta.name)").ws().append(":").ws().append("null;").softNewLine(); - } - if (classSource.get(classClass).getField("name") != null) { - writer.append("cls.").appendField(new FieldReference(classClass, "binaryName")).ws().append("=").ws() - .append("clsProto.$meta.binaryName").ws().append("!==").ws().append("undefined").ws() - .append("?").ws() - .append("$rt_str(clsProto.$meta.binaryName)").ws().append(":").ws().append("null;").softNewLine(); - } - if (classSource.get(classClass).getField("primitive") != null) { - writer.append("cls.").appendField(new FieldReference(classClass, "primitive")) - .append(" = clsProto.$meta.primitive ? 1 : 0;").newLine(); - } - if (classSource.get(classClass).getField("array") != null) { - writer.append("cls.").appendField(new FieldReference(classClass, "array")).ws() - .append("=").ws().append("clsProto.$meta.item").ws().append("?").ws() - .append("1").ws().append(":").ws().append("0;").softNewLine(); - } - if (classSource.get(classClass).getField("isEnum") != null) { - writer.append("cls.").appendField(new FieldReference(classClass, "isEnum")).ws() - .append("=").ws().append("clsProto.$meta.enum").ws().append("?").ws() - .append("1").ws().append(":").ws().append("0;").softNewLine(); - } - writer.append("clsProto.classObject").ws().append("=").ws().append("cls;").softNewLine(); - writer.outdent().append("}").softNewLine(); - writer.append("return cls;").softNewLine(); + writer.append("function $rt_cls(cls)").ws().append("{").softNewLine().indent(); + writer.append("return ").appendMethodBody("java.lang.Class", "getClass", + ValueType.object("org.teavm.platform.PlatformClass"), + ValueType.object("java.lang.Class")).append("(cls);") + .softNewLine(); writer.outdent().append("}").newLine(); } @@ -247,8 +223,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(); } @@ -269,11 +244,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(); @@ -327,6 +301,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())) @@ -349,41 +340,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); } @@ -441,7 +427,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(); @@ -451,11 +437,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(); @@ -480,18 +464,26 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext debugEmitter.emitMethod(method.getReference().getDescriptor()); MethodReference ref = method.getReference(); writer.append(",").newLine(); + String methodName = method.isAsync() ? naming.getNameForAsync(ref) : naming.getNameFor(ref); if (method.isOriginalNamePreserved()) { - writer.append("[\"").appendMethod(ref).append("\",").ws().append("\"").append(ref.getName()) + writer.append("[\"").append(methodName).append("\",").ws().append("\"").append(ref.getName()) .append("\"]"); } else { - writer.append("\"").appendMethod(ref).append("\""); + 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) { @@ -499,13 +491,13 @@ 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); - if (!method.isAsync()) { + if (!method.isAsync() && asyncFamilyMethods.contains(method.getReference())) { writer.append(",").newLine(); writer.append("\"").append(naming.getNameForAsync(ref)).append("\",").ws(); writer.append("$rt_asyncAdapter(").appendMethodBody(ref).append(')'); @@ -713,10 +705,20 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext return async; } + @Override + public boolean isAsync(MethodReference method) { + return asyncMethods.contains(method); + } + @Override public String getCompleteContinuation() { return "$return"; } + + @Override + public Diagnostics getDiagnostics() { + return diagnostics; + } } private void pushLocation(NodeLocation location) { @@ -1471,7 +1473,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()); @@ -1517,7 +1518,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/java/org/teavm/javascript/UnusedVariableEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java index 57845257a..364f3eb50 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java @@ -227,6 +227,9 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor { @Override public void visit(RestoreAsyncStatement statement) { + if (statement.getReceiver() != null) { + statement.setReceiver(renumber(statement.getReceiver())); + } } @Override diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/NativeMethodNode.java b/teavm-core/src/main/java/org/teavm/javascript/ast/NativeMethodNode.java index a58ea263e..921d68919 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/NativeMethodNode.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/NativeMethodNode.java @@ -15,7 +15,7 @@ */ package org.teavm.javascript.ast; -import org.teavm.javascript.ni.Generator; +import org.teavm.javascript.spi.Generator; import org.teavm.model.MethodReference; /** diff --git a/teavm-core/src/main/java/org/teavm/runtime/Async.java b/teavm-core/src/main/java/org/teavm/javascript/spi/Async.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/runtime/Async.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/Async.java index 46047cd78..f20ed7d25 100644 --- a/teavm-core/src/main/java/org/teavm/runtime/Async.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/Async.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.runtime; +package org.teavm.javascript.spi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/GeneratedBy.java b/teavm-core/src/main/java/org/teavm/javascript/spi/GeneratedBy.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/javascript/ni/GeneratedBy.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/GeneratedBy.java index 82d95518b..b74ff7575 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/GeneratedBy.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/GeneratedBy.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/Generator.java b/teavm-core/src/main/java/org/teavm/javascript/spi/Generator.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/javascript/ni/Generator.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/Generator.java index 41abd3cff..973491215 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/Generator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/Generator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.io.IOException; import org.teavm.codegen.SourceWriter; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/GeneratorContext.java b/teavm-core/src/main/java/org/teavm/javascript/spi/GeneratorContext.java similarity index 84% rename from teavm-core/src/main/java/org/teavm/javascript/ni/GeneratorContext.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/GeneratorContext.java index 047d67c0c..927813f0f 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/GeneratorContext.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/GeneratorContext.java @@ -13,11 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.util.Properties; import org.teavm.common.ServiceRepository; +import org.teavm.diagnostics.Diagnostics; import org.teavm.model.ListableClassReaderSource; +import org.teavm.model.MethodReference; /** * @@ -35,4 +37,8 @@ public interface GeneratorContext extends ServiceRepository { boolean isAsync(); String getCompleteContinuation(); + + boolean isAsync(MethodReference method); + + Diagnostics getDiagnostics(); } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/InjectedBy.java b/teavm-core/src/main/java/org/teavm/javascript/spi/InjectedBy.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/javascript/ni/InjectedBy.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/InjectedBy.java index 0398b043b..992262986 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/InjectedBy.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/InjectedBy.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/Injector.java b/teavm-core/src/main/java/org/teavm/javascript/spi/Injector.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/javascript/ni/Injector.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/Injector.java index d67c483fd..8e3ea2cb8 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/Injector.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/Injector.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.io.IOException; import org.teavm.model.MethodReference; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/InjectorContext.java b/teavm-core/src/main/java/org/teavm/javascript/spi/InjectorContext.java similarity index 97% rename from teavm-core/src/main/java/org/teavm/javascript/ni/InjectorContext.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/InjectorContext.java index 71db4a2e9..730c1415c 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/InjectorContext.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/InjectorContext.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.io.IOException; import java.util.Properties; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/PreserveOriginalName.java b/teavm-core/src/main/java/org/teavm/javascript/spi/PreserveOriginalName.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/javascript/ni/PreserveOriginalName.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/PreserveOriginalName.java index dcc53a109..272affd09 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/PreserveOriginalName.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/PreserveOriginalName.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/Remove.java b/teavm-core/src/main/java/org/teavm/javascript/spi/Remove.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/javascript/ni/Remove.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/Remove.java index 9667f9107..723732d88 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/Remove.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/Remove.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/Rename.java b/teavm-core/src/main/java/org/teavm/javascript/spi/Rename.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/javascript/ni/Rename.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/Rename.java index 054c10336..e828610ae 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/Rename.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/Rename.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.lang.annotation.*; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ni/Superclass.java b/teavm-core/src/main/java/org/teavm/javascript/spi/Superclass.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/javascript/ni/Superclass.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/Superclass.java index 3da48b787..8c9b03305 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ni/Superclass.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/Superclass.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.javascript.ni; +package org.teavm.javascript.spi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/teavm-core/src/main/java/org/teavm/runtime/Sync.java b/teavm-core/src/main/java/org/teavm/javascript/spi/Sync.java similarity index 96% rename from teavm-core/src/main/java/org/teavm/runtime/Sync.java rename to teavm-core/src/main/java/org/teavm/javascript/spi/Sync.java index 8b5a68c2a..d43b1acf4 100644 --- a/teavm-core/src/main/java/org/teavm/runtime/Sync.java +++ b/teavm-core/src/main/java/org/teavm/javascript/spi/Sync.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.runtime; +package org.teavm.javascript.spi; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/teavm-core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java b/teavm-core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java index 4c07b28bd..78f89b64c 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java +++ b/teavm-core/src/main/java/org/teavm/model/util/AsyncMethodFinder.java @@ -15,16 +15,15 @@ */ package org.teavm.model.util; -import java.util.HashSet; -import java.util.Set; +import java.util.*; import org.teavm.callgraph.CallGraph; import org.teavm.callgraph.CallGraphNode; import org.teavm.callgraph.CallSite; import org.teavm.diagnostics.Diagnostics; -import org.teavm.javascript.ni.InjectedBy; +import org.teavm.javascript.spi.Async; +import org.teavm.javascript.spi.InjectedBy; +import org.teavm.javascript.spi.Sync; import org.teavm.model.*; -import org.teavm.runtime.Async; -import org.teavm.runtime.Sync; /** * @@ -32,6 +31,9 @@ import org.teavm.runtime.Sync; */ public class AsyncMethodFinder { private Set asyncMethods = new HashSet<>(); + private Map asyncFamilyMethods = new HashMap<>(); + private Set readonlyAsyncMethods = Collections.unmodifiableSet(asyncMethods); + private Set readonlyAsyncFamilyMethods = Collections.unmodifiableSet(asyncFamilyMethods.keySet()); private CallGraph callGraph; private Diagnostics diagnostics; private ListableClassReaderSource classSource; @@ -42,7 +44,11 @@ public class AsyncMethodFinder { } public Set getAsyncMethods() { - return asyncMethods; + return readonlyAsyncMethods; + } + + public Set getAsyncFamilyMethods() { + return readonlyAsyncFamilyMethods; } public void find(ListableClassReaderSource classSource) { @@ -58,6 +64,17 @@ public class AsyncMethodFinder { } } } + for (String clsName : classSource.getClassNames()) { + ClassReader cls = classSource.get(clsName); + for (MethodReader method : cls.getMethods()) { + addToFamily(method.getReference()); + } + } + for (Map.Entry entry : new ArrayList<>(asyncFamilyMethods.entrySet())) { + if (!entry.getValue()) { + asyncFamilyMethods.remove(entry.getKey()); + } + } } private void add(MethodReference methodRef) { @@ -85,5 +102,76 @@ public class AsyncMethodFinder { for (CallSite callSite : node.getCallerCallSites()) { add(callSite.getCaller().getMethod()); } + Set visited = new HashSet<>(); + Set overriden = new HashSet<>(); + if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) { + findOverridenMethods(new MethodReference(cls.getParent(), methodRef.getDescriptor()), overriden, visited); + } + for (String iface : cls.getInterfaces()) { + findOverridenMethods(new MethodReference(iface, methodRef.getDescriptor()), overriden, visited); + } + for (MethodReference overridenMethod : overriden) { + add(overridenMethod); + } + } + + private boolean addToFamily(MethodReference methodRef) { + Boolean cachedResult = asyncFamilyMethods.get(methodRef); + if (cachedResult != null) { + return cachedResult; + } + boolean result = addToFamilyCacheMiss(methodRef); + asyncFamilyMethods.put(methodRef, result); + return result; + } + + private boolean addToFamilyCacheMiss(MethodReference methodRef) { + if (asyncMethods.contains(methodRef)) { + return true; + } + ClassReader cls = classSource.get(methodRef.getClassName()); + if (cls == null) { + return false; + } + List parents = new ArrayList<>(); + if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) { + parents.add(cls.getParent()); + } + parents.addAll(cls.getInterfaces()); + + Set visited = new HashSet<>(); + Set overriden = new HashSet<>(); + for (String parent : parents) { + findOverridenMethods(new MethodReference(parent, methodRef.getDescriptor()), overriden, visited); + } + + for (MethodReference overridenMethod : overriden) { + if (addToFamily(overridenMethod)) { + return true; + } + } + return false; + } + + private void findOverridenMethods(MethodReference methodRef, Set result, + Set visited) { + if (!visited.add(methodRef)) { + return; + } + ClassReader cls = classSource.get(methodRef.getClassName()); + if (cls == null) { + return; + } + MethodReader method = cls.getMethod(methodRef.getDescriptor()); + if (method != null) { + result.add(methodRef); + } else { + if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) { + findOverridenMethods(new MethodReference(cls.getParent(), methodRef.getDescriptor()), result, visited); + } + for (String iface : cls.getInterfaces()) { + findOverridenMethods(new MethodReference(iface, methodRef.getDescriptor()), result, visited); + } + } } } diff --git a/teavm-core/src/main/java/org/teavm/parsing/ClassRefsRenamer.java b/teavm-core/src/main/java/org/teavm/parsing/ClassRefsRenamer.java index 921b9d700..078066b2b 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/ClassRefsRenamer.java +++ b/teavm-core/src/main/java/org/teavm/parsing/ClassRefsRenamer.java @@ -17,9 +17,9 @@ package org.teavm.parsing; import java.util.Map; import org.teavm.common.Mapper; -import org.teavm.javascript.ni.Remove; -import org.teavm.javascript.ni.Rename; -import org.teavm.javascript.ni.Superclass; +import org.teavm.javascript.spi.Remove; +import org.teavm.javascript.spi.Rename; +import org.teavm.javascript.spi.Superclass; import org.teavm.model.*; import org.teavm.model.instructions.*; import org.teavm.model.util.ModelUtils; diff --git a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java index cf333c617..77b16c7fa 100644 --- a/teavm-core/src/main/java/org/teavm/vm/TeaVM.java +++ b/teavm-core/src/main/java/org/teavm/vm/TeaVM.java @@ -26,10 +26,10 @@ import org.teavm.diagnostics.AccumulationDiagnostics; import org.teavm.diagnostics.ProblemProvider; import org.teavm.javascript.*; import org.teavm.javascript.ast.ClassNode; -import org.teavm.javascript.ni.GeneratedBy; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.InjectedBy; -import org.teavm.javascript.ni.Injector; +import org.teavm.javascript.spi.GeneratedBy; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.InjectedBy; +import org.teavm.javascript.spi.Injector; import org.teavm.model.*; import org.teavm.model.instructions.*; import org.teavm.model.util.*; @@ -90,6 +90,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository { private boolean cancelled; private ListableClassHolderSource writtenClasses; private Set asyncMethods = new HashSet<>(); + private Set asyncFamilyMethods = new HashSet<>(); TeaVM(ClassReaderSource classSource, ClassLoader classLoader) { this.classSource = classSource; @@ -334,7 +335,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository { return progressListener.progressReached(0) == TeaVMProgressFeedback.CONTINUE; } }); - dependencyChecker.linkMethod(new MethodReference(Class.class, "createNew", Class.class), null).use(); + dependencyChecker.linkMethod(new MethodReference(Class.class.getName(), "getClass", + ValueType.object("org.teavm.platform.PlatformClass"), ValueType.parse(Class.class)), null).use(); dependencyChecker.linkMethod(new MethodReference(String.class, "", char[].class, void.class), null).use(); dependencyChecker.linkMethod(new MethodReference(String.class, "getChars", int.class, int.class, char[].class, @@ -400,7 +402,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository { SourceWriterBuilder builder = new SourceWriterBuilder(naming); builder.setMinified(minifying); SourceWriter sourceWriter = builder.build(writer); - Renderer renderer = new Renderer(sourceWriter, classSet, classLoader, this); + Renderer renderer = new Renderer(sourceWriter, classSet, classLoader, this, asyncMethods, asyncFamilyMethods, + diagnostics); renderer.setProperties(properties); if (debugEmitter != null) { int classIndex = 0; @@ -564,6 +567,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository { AsyncMethodFinder asyncFinder = new AsyncMethodFinder(dependencyChecker.getCallGraph(), diagnostics); asyncFinder.find(classes); asyncMethods.addAll(asyncFinder.getAsyncMethods()); + asyncFamilyMethods.addAll(asyncFinder.getAsyncFamilyMethods()); progressListener.phaseStarted(TeaVMPhase.DECOMPILATION, classes.getClassNames().size()); Decompiler decompiler = new Decompiler(classes, classLoader, asyncFinder.getAsyncMethods()); diff --git a/teavm-core/src/main/java/org/teavm/vm/spi/TeaVMHost.java b/teavm-core/src/main/java/org/teavm/vm/spi/TeaVMHost.java index 59a38ab52..10a8e6c15 100644 --- a/teavm-core/src/main/java/org/teavm/vm/spi/TeaVMHost.java +++ b/teavm-core/src/main/java/org/teavm/vm/spi/TeaVMHost.java @@ -17,8 +17,8 @@ package org.teavm.vm.spi; import java.util.Properties; import org.teavm.dependency.DependencyListener; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.Injector; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.Injector; import org.teavm.model.ClassHolderTransformer; import org.teavm.model.MethodReference; import org.teavm.vm.TeaVM; 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 ec2a05e12..01d74640a 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -130,15 +130,18 @@ function $rt_arraycls(cls) { } var name = "[" + cls.$meta.binaryName; arraycls.$meta = { item : cls, supertypes : [$rt_objcls()], primitive : false, superclass : $rt_objcls(), - name : name, binaryName : name }; + name : name, binaryName : name, enum : false }; + arraycls.classObject = null; cls.$array = arraycls; } return cls.$array; } function $rt_createcls() { return { + classObject : null, $meta : { - supertypes : [] + supertypes : [], + superclass : null } }; } @@ -147,6 +150,8 @@ function $rt_createPrimitiveCls(name, binaryName) { cls.$meta.primitive = true; cls.$meta.name = name; cls.$meta.binaryName = binaryName; + cls.$meta.enum = false; + cls.$meta.item = null; return cls; } var $rt_booleanclsCache = null; @@ -365,19 +370,22 @@ function $rt_putStderr(ch) { } function $rt_declClass(cls, data) { cls.$meta = {}; - cls.$meta.superclass = data.superclass; - cls.$meta.supertypes = data.interfaces ? data.interfaces.slice() : []; + var m = cls.$meta + m.superclass = typeof(data.superclass) !== 'undefined' ? data.superclass : null; + m.supertypes = data.interfaces ? data.interfaces.slice() : []; if (data.superclass) { - cls.$meta.supertypes.push(data.superclass); + m.supertypes.push(data.superclass); cls.prototype = new data.superclass(); } else { cls.prototype = new Object(); } - cls.$meta.name = data.name; - cls.$meta.binaryName = "L" + data.name + ";"; - cls.$meta.enum = data.enum; + m.name = data.name; + m.binaryName = "L" + data.name + ";"; + m.enum = data.enum; + m.item = null; cls.prototype.constructor = cls; - cls.$clinit = data.clinit; + cls.classObject = null; + cls.$clinit = data.clinit ? data.clinit : function() {}; } function $rt_virtualMethods(cls) { for (var i = 1; i < arguments.length; i += 2) { @@ -404,7 +412,6 @@ function $rt_asyncError(e) { } function $rt_asyncAdapter(f) { return function() { - var e; var result; var args = Array.prototype.slice.apply(arguments); var $return = args.pop(); @@ -419,11 +426,6 @@ function $rt_asyncAdapter(f) { function $rt_rootInvocationAdapter(f, extraArgs) { return function() { var args = Array.prototype.slice.apply(arguments); - if (extraArgs) { - for (var i = 0; i < extraArts.length; ++i) { - args.push(extraArgs[i]); - } - } args.push(function(result) { result(); }); diff --git a/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js b/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js index 411fca35a..18f25d016 100644 --- a/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js +++ b/teavm-core/src/main/resources/org/teavm/tooling/test/res/junit-support.js @@ -370,11 +370,11 @@ var JUnitClient = {}; JUnitClient.run = function() { var handler = window.addEventListener("message", function() { window.removeEventListener("message", handler); + var message = {}; try { var instance = new TestClass(); initInstance(instance); runTest(instance, function(restore) { - var message = {}; try { var result = restore(); message.status = "ok"; diff --git a/teavm-dom/src/main/java/org/teavm/dom/browser/Window.java b/teavm-dom/src/main/java/org/teavm/dom/browser/Window.java index ab8263a11..93b28b8a9 100644 --- a/teavm-dom/src/main/java/org/teavm/dom/browser/Window.java +++ b/teavm-dom/src/main/java/org/teavm/dom/browser/Window.java @@ -29,7 +29,7 @@ import org.teavm.jso.JSProperty; * * @author Alexey Andreev */ -public interface Window extends JSGlobal, EventTarget, StorageProvider { +public interface Window extends JSGlobal, EventTarget, StorageProvider, TypedArrayFactory { @JSProperty HTMLDocument getDocument(); @@ -42,10 +42,14 @@ public interface Window extends JSGlobal, EventTarget, StorageProvider { int setTimeout(TimerHandler handler, int delay); + int setTimeout(TimerHandler handler, double delay); + void clearTimeout(int timeoutId); int setInterval(TimerHandler handler, int delay); + int setInterval(TimerHandler handler, double delay); + void clearInterval(int timeoutId); @JSProperty("JSON") @@ -53,79 +57,4 @@ public interface Window extends JSGlobal, EventTarget, StorageProvider { @JSConstructor("XMLHttpRequest") XMLHttpRequest createXMLHttpRequest(); - - @JSConstructor("ArrayBuffer") - ArrayBuffer createArrayBuffer(int length); - - @JSConstructor("Int8Array") - Int8Array createInt8Array(int length); - - @JSConstructor("Int8Array") - Int8Array createInt8Array(ArrayBuffer buffer); - - @JSConstructor("Int8Array") - Int8Array createInt8Array(ArrayBuffer buffer, int offset, int length); - - @JSConstructor("Uint8Array") - Uint8Array createUint8Array(int length); - - @JSConstructor("Uint8Array") - Uint8Array createUint8Array(ArrayBuffer buffer); - - @JSConstructor("Uint8Array") - Uint8Array createUint8Array(ArrayBuffer buffer, int offset, int length); - - @JSConstructor("Uint8ClampedArray") - Uint8ClampedArray createUint8ClampedArray(int length); - - @JSConstructor("Uint8ClampedArray") - Uint8ClampedArray createUint8ClampedArray(ArrayBuffer buffer); - - @JSConstructor("Uint8ClampedArray") - Uint8ClampedArray createUintClamped8Array(ArrayBuffer buffer, int offset, int length); - - @JSConstructor("Int16Array") - Int16Array createInt16Array(int length); - - @JSConstructor("Int16Array") - Int16Array createInt16Array(ArrayBuffer buffer); - - @JSConstructor("Int16Array") - Int16Array createInt16Array(ArrayBuffer buffer, int offset, int length); - - @JSConstructor("Uint16Array") - Uint16Array createUint16Array(int length); - - @JSConstructor("Uint16Array") - Uint16Array createUint16Array(ArrayBuffer buffer); - - @JSConstructor("Uint16Array") - Uint16Array createUint16Array(ArrayBuffer buffer, int offset, int length); - - @JSConstructor("Int32Array") - Int32Array createInt32Array(int length); - - @JSConstructor("Int32Array") - Int32Array createInt32Array(ArrayBuffer buffer); - - @JSConstructor("Int32Array") - Int32Array createInt32Array(ArrayBuffer buffer, int offset, int length); - - @JSConstructor("Float32Array") - Float32Array createFloat32Array(int length); - - @JSConstructor("Float32Array") - Float32Array createFloat32Array(ArrayBuffer buffer); - - @JSConstructor("Float32Array") - Float32Array createFloat32Array(ArrayBuffer buffer, int offset, int length); - - @JSConstructor("Float64Array") - Float64Array createFloat64Array(int length); - - @JSConstructor("Float64Array") - Float64Array createFloat64Array(ArrayBuffer buffer); - - @JSConstructor("Float64Array") - Float64Array createFloat64Array(ArrayBuffer buffer, int offset, int length); } diff --git a/teavm-dom/src/main/java/org/teavm/dom/typedarrays/TypedArrayFactory.java b/teavm-dom/src/main/java/org/teavm/dom/typedarrays/TypedArrayFactory.java new file mode 100644 index 000000000..33086480e --- /dev/null +++ b/teavm-dom/src/main/java/org/teavm/dom/typedarrays/TypedArrayFactory.java @@ -0,0 +1,100 @@ +/* + * Copyright 2015 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.dom.typedarrays; + +import org.teavm.jso.JSConstructor; +import org.teavm.jso.JSObject; + +/** + * + * @author Alexey Andreev + */ +public interface TypedArrayFactory extends JSObject { + @JSConstructor("ArrayBuffer") + ArrayBuffer createArrayBuffer(int length); + + @JSConstructor("Int8Array") + Int8Array createInt8Array(int length); + + @JSConstructor("Int8Array") + Int8Array createInt8Array(ArrayBuffer buffer); + + @JSConstructor("Int8Array") + Int8Array createInt8Array(ArrayBuffer buffer, int offset, int length); + + @JSConstructor("Uint8Array") + Uint8Array createUint8Array(int length); + + @JSConstructor("Uint8Array") + Uint8Array createUint8Array(ArrayBuffer buffer); + + @JSConstructor("Uint8Array") + Uint8Array createUint8Array(ArrayBuffer buffer, int offset, int length); + + @JSConstructor("Uint8ClampedArray") + Uint8ClampedArray createUint8ClampedArray(int length); + + @JSConstructor("Uint8ClampedArray") + Uint8ClampedArray createUint8ClampedArray(ArrayBuffer buffer); + + @JSConstructor("Uint8ClampedArray") + Uint8ClampedArray createUintClamped8Array(ArrayBuffer buffer, int offset, int length); + + @JSConstructor("Int16Array") + Int16Array createInt16Array(int length); + + @JSConstructor("Int16Array") + Int16Array createInt16Array(ArrayBuffer buffer); + + @JSConstructor("Int16Array") + Int16Array createInt16Array(ArrayBuffer buffer, int offset, int length); + + @JSConstructor("Uint16Array") + Uint16Array createUint16Array(int length); + + @JSConstructor("Uint16Array") + Uint16Array createUint16Array(ArrayBuffer buffer); + + @JSConstructor("Uint16Array") + Uint16Array createUint16Array(ArrayBuffer buffer, int offset, int length); + + @JSConstructor("Int32Array") + Int32Array createInt32Array(int length); + + @JSConstructor("Int32Array") + Int32Array createInt32Array(ArrayBuffer buffer); + + @JSConstructor("Int32Array") + Int32Array createInt32Array(ArrayBuffer buffer, int offset, int length); + + @JSConstructor("Float32Array") + Float32Array createFloat32Array(int length); + + @JSConstructor("Float32Array") + Float32Array createFloat32Array(ArrayBuffer buffer); + + @JSConstructor("Float32Array") + Float32Array createFloat32Array(ArrayBuffer buffer, int offset, int length); + + @JSConstructor("Float64Array") + Float64Array createFloat64Array(int length); + + @JSConstructor("Float64Array") + Float64Array createFloat64Array(ArrayBuffer buffer); + + @JSConstructor("Float64Array") + Float64Array createFloat64Array(ArrayBuffer buffer, int offset, int length); +} diff --git a/teavm-eclipse/teavm-eclipse-core-plugin/META-INF/MANIFEST.MF b/teavm-eclipse/teavm-eclipse-core-plugin/META-INF/MANIFEST.MF index 2d20e3fa8..751ae8231 100644 --- a/teavm-eclipse/teavm-eclipse-core-plugin/META-INF/MANIFEST.MF +++ b/teavm-eclipse/teavm-eclipse-core-plugin/META-INF/MANIFEST.MF @@ -59,7 +59,7 @@ Export-Package: org.teavm.cache, org.teavm.diagnostics, org.teavm.javascript, org.teavm.javascript.ast, - org.teavm.javascript.ni, + org.teavm.javascript.spi, org.teavm.model, org.teavm.model.instructions, org.teavm.model.util, diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyGenerator.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyGenerator.java index 12e1222b0..75f46c9ae 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyGenerator.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyGenerator.java @@ -21,8 +21,8 @@ import net.java.html.js.JavaScriptBody; import org.teavm.codegen.NamingStrategy; import org.teavm.codegen.SourceWriter; import org.teavm.javascript.Renderer; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.*; /** diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java index 6cadd5a07..b92d0afdb 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptBodyTransformer.java @@ -17,7 +17,7 @@ package org.teavm.html4j; import net.java.html.js.JavaScriptBody; import org.teavm.diagnostics.Diagnostics; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; import org.teavm.model.*; /** diff --git a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConv.java b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConv.java index 9d7b41127..8183887cb 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConv.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConv.java @@ -15,7 +15,7 @@ */ package org.teavm.html4j; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; /** * 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 5a9743509..a26227dd0 100644 --- a/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConvGenerator.java +++ b/teavm-html4j/src/main/java/org/teavm/html4j/JavaScriptConvGenerator.java @@ -17,8 +17,8 @@ package org.teavm.html4j; import java.io.IOException; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.*; /** diff --git a/teavm-jso/pom.xml b/teavm-jso/pom.xml index a42c91397..8b70a0006 100644 --- a/teavm-jso/pom.xml +++ b/teavm-jso/pom.xml @@ -43,42 +43,6 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs - - org.teavm - teavm-maven-plugin - ${project.version} - - - org.teavm - teavm-classlib - ${project.version} - - - - - generate-javascript-tests - - build-test-javascript - - process-test-classes - - false - - en, en_US, en_GB, ru, ru_RU - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - ** - - - org.apache.maven.plugins maven-checkstyle-plugin diff --git a/teavm-jso/src/main/java/org/teavm/jso/JS.java b/teavm-jso/src/main/java/org/teavm/jso/JS.java index 0481c80e2..bd99b5f6f 100644 --- a/teavm-jso/src/main/java/org/teavm/jso/JS.java +++ b/teavm-jso/src/main/java/org/teavm/jso/JS.java @@ -17,7 +17,7 @@ package org.teavm.jso; import java.util.Iterator; import org.teavm.dependency.PluggableDependency; -import org.teavm.javascript.ni.InjectedBy; +import org.teavm.javascript.spi.InjectedBy; import org.teavm.jso.plugin.JSNativeGenerator; /** @@ -101,6 +101,9 @@ public final class JS { @InjectedBy(JSNativeGenerator.class) public static native JSObject wrap(short num); + @InjectedBy(JSNativeGenerator.class) + public static native JSObject marshall(Object obj); + public static JSArray wrap(T[] array) { JSArray result = createArray(array.length); for (int i = 0; i < array.length; ++i) { diff --git a/teavm-jso/src/main/java/org/teavm/jso/plugin/JSBodyGenerator.java b/teavm-jso/src/main/java/org/teavm/jso/plugin/JSBodyGenerator.java index 25bbb4092..f2c7ed50c 100644 --- a/teavm-jso/src/main/java/org/teavm/jso/plugin/JSBodyGenerator.java +++ b/teavm-jso/src/main/java/org/teavm/jso/plugin/JSBodyGenerator.java @@ -18,8 +18,8 @@ package org.teavm.jso.plugin; import java.io.IOException; import java.util.List; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.*; /** diff --git a/teavm-jso/src/main/java/org/teavm/jso/plugin/JSNativeGenerator.java b/teavm-jso/src/main/java/org/teavm/jso/plugin/JSNativeGenerator.java index 856aa0dc9..1bb899f8b 100644 --- a/teavm-jso/src/main/java/org/teavm/jso/plugin/JSNativeGenerator.java +++ b/teavm-jso/src/main/java/org/teavm/jso/plugin/JSNativeGenerator.java @@ -21,8 +21,8 @@ import org.teavm.dependency.*; import org.teavm.javascript.ast.ConstantExpr; import org.teavm.javascript.ast.Expr; import org.teavm.javascript.ast.InvocationExpr; -import org.teavm.javascript.ni.Injector; -import org.teavm.javascript.ni.InjectorContext; +import org.teavm.javascript.spi.Injector; +import org.teavm.javascript.spi.InjectorContext; import org.teavm.jso.JS; import org.teavm.model.CallLocation; import org.teavm.model.ClassReader; @@ -88,6 +88,9 @@ public class JSNativeGenerator implements Injector, DependencyPlugin { } writer.append("))"); break; + case "marshall": + context.writeExpr(context.getArgument(0)); + break; case "wrap": if (methodRef.getDescriptor().parameterType(0).isObject("java.lang.String")) { writer.append("$rt_ustr("); diff --git a/teavm-jso/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java b/teavm-jso/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java index b2d44ab55..af8872317 100644 --- a/teavm-jso/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java +++ b/teavm-jso/src/main/java/org/teavm/jso/plugin/JavascriptNativeProcessor.java @@ -17,8 +17,8 @@ package org.teavm.jso.plugin; import java.util.*; import org.teavm.diagnostics.Diagnostics; -import org.teavm.javascript.ni.GeneratedBy; -import org.teavm.javascript.ni.PreserveOriginalName; +import org.teavm.javascript.spi.GeneratedBy; +import org.teavm.javascript.spi.PreserveOriginalName; import org.teavm.jso.*; import org.teavm.model.*; import org.teavm.model.instructions.*; diff --git a/teavm-platform/pom.xml b/teavm-platform/pom.xml index 9388726fa..a9ea6d967 100644 --- a/teavm-platform/pom.xml +++ b/teavm-platform/pom.xml @@ -35,6 +35,16 @@ teavm-core ${project.version} + + org.teavm + teavm-jso + ${project.version} + + + org.teavm + teavm-dom + ${project.version} + junit junit diff --git a/teavm-platform/src/main/java/org/teavm/platform/Platform.java b/teavm-platform/src/main/java/org/teavm/platform/Platform.java new file mode 100644 index 000000000..38c43fcfd --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/Platform.java @@ -0,0 +1,98 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.dependency.PluggableDependency; +import org.teavm.javascript.spi.GeneratedBy; +import org.teavm.javascript.spi.InjectedBy; +import org.teavm.jso.JS; +import org.teavm.platform.metadata.ClassResource; +import org.teavm.platform.plugin.PlatformGenerator; + +/** + * + * @author Alexey Andreev + */ +public final class Platform { + private Platform() { + } + + public static PlatformObject getPlatformObject(Object obj) { + return (PlatformObject)JS.marshall(obj); + } + + @GeneratedBy(PlatformGenerator.class) + @PluggableDependency(PlatformGenerator.class) + public static native Object clone(Object obj); + + public static boolean isInstance(PlatformObject obj, PlatformClass cls) { + return obj != null && !JS.isUndefined(obj.getPlatformClass().getMetadata()) && + isAssignable(obj.getPlatformClass(), cls); + } + + public static boolean isAssignable(PlatformClass from, PlatformClass to) { + if (from == to) { + return true; + } + PlatformSequence supertypes = from.getMetadata().getSupertypes(); + for (int i = 0; i < supertypes.getLength(); ++i) { + if (isAssignable(supertypes.get(i), to)) { + return true; + } + } + return false; + } + + @InjectedBy(PlatformGenerator.class) + @PluggableDependency(PlatformGenerator.class) + public static native Class asJavaClass(PlatformObject obj); + + public static PlatformPrimitives getPrimitives() { + return (PlatformPrimitives)JS.getGlobal(); + } + + public static PlatformConsole getConsole() { + return (PlatformConsole)JS.getGlobal(); + } + + public static int nextObjectId() { + return ((PlatformHelper)JS.getGlobal()).nextId(); + } + + @GeneratedBy(PlatformGenerator.class) + @PluggableDependency(PlatformGenerator.class) + public static native T newInstance(PlatformClass cls); + + @GeneratedBy(PlatformGenerator.class) + @PluggableDependency(PlatformGenerator.class) + public static native PlatformClass lookupClass(String name); + + @GeneratedBy(PlatformGenerator.class) + @PluggableDependency(PlatformGenerator.class) + public static native void initClass(PlatformClass cls); + + @InjectedBy(PlatformGenerator.class) + @PluggableDependency(PlatformGenerator.class) + public static native PlatformClass classFromResource(ClassResource resource); + + @InjectedBy(PlatformGenerator.class) + @PluggableDependency(PlatformGenerator.class) + public static native Enum[] getEnumConstants(PlatformClass cls); + + public static PlatformString stringFromCharCode(int charCode) { + return ((PlatformHelper)JS.getGlobal()).getStringClass().fromCharCode(charCode); + } +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformClass.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformClass.java new file mode 100644 index 000000000..abb9bcd46 --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformClass.java @@ -0,0 +1,34 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +/** + * + * @author Alexey Andreev + */ +public interface PlatformClass extends JSObject { + @JSProperty("$meta") + PlatformClassMetadata getMetadata(); + + @JSProperty("classObject") + void setJavaClass(PlatformObject obj); + + @JSProperty("classObject") + PlatformObject getJavaClass(); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformClassMetadata.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformClassMetadata.java new file mode 100644 index 000000000..d17dfc703 --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformClassMetadata.java @@ -0,0 +1,43 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +/** + * + * @author Alexey Andreev + */ +public interface PlatformClassMetadata extends JSObject { + @JSProperty("item") + PlatformClass getArrayItem(); + + @JSProperty + PlatformSequence getSupertypes(); + + @JSProperty + PlatformClass getSuperclass(); + + @JSProperty + String getName(); + + @JSProperty + boolean isPrimitive(); + + @JSProperty + boolean isEnum(); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformConsole.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformConsole.java new file mode 100644 index 000000000..2db3a7a7f --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformConsole.java @@ -0,0 +1,31 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSMethod; +import org.teavm.jso.JSObject; + +/** + * + * @author Alexey Andreev + */ +public interface PlatformConsole extends JSObject { + @JSMethod("rt_putStdout") + void output(int b); + + @JSMethod("rt_putStderr") + void error(int b); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformHelper.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformHelper.java new file mode 100644 index 000000000..48f851b2c --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformHelper.java @@ -0,0 +1,32 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSMethod; +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +/** + * + * @author Alexey Andreev + */ +interface PlatformHelper extends JSObject { + @JSMethod("$rt_nextId") + int nextId(); + + @JSProperty("String") + PlatformStringClass getStringClass(); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformObject.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformObject.java new file mode 100644 index 000000000..0c18bec4a --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformObject.java @@ -0,0 +1,34 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +/** + * + * @author Alexey Andreev + */ +public interface PlatformObject extends JSObject { + @JSProperty("constructor") + PlatformClass getPlatformClass(); + + @JSProperty("$id") + int getId(); + + @JSProperty("$id") + void setId(int id); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformPrimitives.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformPrimitives.java new file mode 100644 index 000000000..7a7556958 --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformPrimitives.java @@ -0,0 +1,52 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSMethod; +import org.teavm.jso.JSObject; + +/** + * + * @author Alexey Andreev + */ +public interface PlatformPrimitives extends JSObject { + @JSMethod("$rt_voidcls") + PlatformClass getVoidClass(); + + @JSMethod("$rt_booleancls") + PlatformClass getBooleanClass(); + + @JSMethod("$rt_bytecls") + PlatformClass getByteClass(); + + @JSMethod("$rt_shortcls") + PlatformClass getShortClass(); + + @JSMethod("$rt_charcls") + PlatformClass getCharClass(); + + @JSMethod("$rt_intcls") + PlatformClass getIntClass(); + + @JSMethod("$rt_longcls") + PlatformClass getLongClass(); + + @JSMethod("$rt_floatcls") + PlatformClass getFloatClass(); + + @JSMethod("$rt_doublecls") + PlatformClass getDoubleClass(); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformSequence.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformSequence.java new file mode 100644 index 000000000..213277406 --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformSequence.java @@ -0,0 +1,32 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSIndexer; +import org.teavm.jso.JSObject; +import org.teavm.jso.JSProperty; + +/** + * + * @author Alexey Andreev + */ +public interface PlatformSequence extends JSObject { + @JSProperty + int getLength(); + + @JSIndexer + T get(int index); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformString.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformString.java new file mode 100644 index 000000000..6b83bda7f --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformString.java @@ -0,0 +1,30 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSObject; + +/** + * + * @author Alexey Andreev + */ +public interface PlatformString extends JSObject { + PlatformString toUpperCase(); + + PlatformString toLowerCase(); + + int charCodeAt(int index); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/PlatformStringClass.java b/teavm-platform/src/main/java/org/teavm/platform/PlatformStringClass.java new file mode 100644 index 000000000..45633f34e --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/PlatformStringClass.java @@ -0,0 +1,26 @@ +/* + * Copyright 2015 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.platform; + +import org.teavm.jso.JSObject; + +/** + * + * @author Alexey Andreev + */ +interface PlatformStringClass extends JSObject { + PlatformString fromCharCode(int charCode); +} diff --git a/teavm-core/src/main/java/org/teavm/runtime/AsyncCallback.java b/teavm-platform/src/main/java/org/teavm/platform/async/AsyncCallback.java similarity index 82% rename from teavm-core/src/main/java/org/teavm/runtime/AsyncCallback.java rename to teavm-platform/src/main/java/org/teavm/platform/async/AsyncCallback.java index 8579eab71..675bacd19 100644 --- a/teavm-core/src/main/java/org/teavm/runtime/AsyncCallback.java +++ b/teavm-platform/src/main/java/org/teavm/platform/async/AsyncCallback.java @@ -13,14 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.runtime; +package org.teavm.platform.async; /** * - * @author Alexey Andreev + * @author Alexey Andreev */ public interface AsyncCallback { - void complete(T value); + void complete(T result); - void error(Exception e); + void error(Throwable e); } diff --git a/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassResource.java b/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassResource.java new file mode 100644 index 000000000..143bf608c --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassResource.java @@ -0,0 +1,23 @@ +/* + * Copyright 2015 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.platform.metadata; + +/** + * + * @author Alexey Andreev + */ +public interface ClassResource extends Resource { +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataGenerator.java b/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataGenerator.java new file mode 100644 index 000000000..a884bfac2 --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataGenerator.java @@ -0,0 +1,35 @@ +/* + * Copyright 2015 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.platform.metadata; + +import java.util.Map; +import org.teavm.model.MethodReference; +import org.teavm.platform.PlatformClass; + +/** + *

Behaviour of this class is similar to {@link MetadataGenerator}. The difference is that method, marked with + * {@link ClassScopedMetadataProvider} must take one argument of type {@link PlatformClass}. It will + * return different resource for each given class, corresponding to map entries, produced by + * {@link #generateMetadata(MetadataGeneratorContext, MethodReference)}. + * + * @see ClassScopedMetadataProvider + * @see MetadataGenerator + * + * @author Alexey Andreev + */ +public interface ClassScopedMetadataGenerator { + Map generateMetadata(MetadataGeneratorContext context, MethodReference method); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataProvider.java b/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataProvider.java new file mode 100644 index 000000000..617cc36fc --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/metadata/ClassScopedMetadataProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 2015 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.platform.metadata; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + *

Binds a {@link ClassScopedMetadataGenerator} to a native method.

+ * + * @see MetadataProvider + * + * @author Alexey Andreev + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ClassScopedMetadataProvider { + Class value(); +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/metadata/MetadataGenerator.java b/teavm-platform/src/main/java/org/teavm/platform/metadata/MetadataGenerator.java index 92c0ce73a..5ca4546d6 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/metadata/MetadataGenerator.java +++ b/teavm-platform/src/main/java/org/teavm/platform/metadata/MetadataGenerator.java @@ -50,6 +50,8 @@ import org.teavm.model.MethodReference; * *

All other types are not considered to be resources and therefore are not accepted.

* + * @see ClassScopedMetadataGenerator + * * @author Alexey Andreev */ public interface MetadataGenerator { diff --git a/teavm-platform/src/main/java/org/teavm/platform/metadata/MetadataGeneratorContext.java b/teavm-platform/src/main/java/org/teavm/platform/metadata/MetadataGeneratorContext.java index 067b4fe26..e505fed5e 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/metadata/MetadataGeneratorContext.java +++ b/teavm-platform/src/main/java/org/teavm/platform/metadata/MetadataGeneratorContext.java @@ -18,6 +18,7 @@ package org.teavm.platform.metadata; import java.util.Properties; import org.teavm.common.ServiceRepository; import org.teavm.model.ListableClassReaderSource; +import org.teavm.platform.Platform; import org.teavm.vm.TeaVM; /** @@ -48,6 +49,12 @@ public interface MetadataGeneratorContext extends ServiceRepository { */ T createResource(Class resourceType); + /** + * Creates a new resource that represents class literal. Client code then may use + * {@link Platform#classFromResource(ClassResource)} to get actual class. + */ + ClassResource createClassResource(String className); + /** * Creates a new resource array. */ diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/AsyncMethodGenerator.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/AsyncMethodGenerator.java new file mode 100644 index 000000000..2dfbc2878 --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/AsyncMethodGenerator.java @@ -0,0 +1,85 @@ +/* + * Copyright 2015 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.platform.plugin; + +import java.io.IOException; +import org.teavm.codegen.SourceWriter; +import org.teavm.dependency.DependencyAgent; +import org.teavm.dependency.DependencyPlugin; +import org.teavm.dependency.MethodDependency; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; +import org.teavm.model.*; +import org.teavm.platform.async.AsyncCallback; + +/** + * + * @author Alexey Andreev + */ +public class AsyncMethodGenerator implements Generator, DependencyPlugin { + private static final MethodReference completeMethod = new MethodReference(AsyncCallback.class, "complete", + Object.class, void.class); + private static final MethodReference errorMethod = new MethodReference(AsyncCallback.class, "error", + Throwable.class, void.class); + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { + MethodReference asyncRef = getAsyncReference(methodRef); + writer.append("var callback").ws().append("=").ws().append("function()").ws().append("{}").softNewLine(); + writer.append("callback.").appendMethod(completeMethod).ws().append("=").ws().append("function($this,").ws() + .append("val)").ws().append("{").indent().softNewLine(); + writer.append("return $return($rt_asyncResult(val));").softNewLine(); + writer.outdent().append("};").softNewLine(); + writer.append("callback.").appendMethod(errorMethod).ws().append("=").ws().append("function($this,").ws() + .append("e)").ws().append("{").indent().softNewLine(); + writer.append("return $return($rt_asyncError(e));").softNewLine(); + writer.outdent().append("};").softNewLine(); + writer.append("try").ws().append("{").indent().softNewLine(); + writer.append("return ").appendMethodBody(asyncRef).append('('); + ClassReader cls = context.getClassSource().get(methodRef.getClassName()); + MethodReader method = cls.getMethod(methodRef.getDescriptor()); + int start = method.hasModifier(ElementModifier.STATIC) ? 1 : 0; + for (int i = start; i <= methodRef.parameterCount(); ++i) { + writer.append(context.getParameterName(i)); + writer.append(',').ws(); + } + writer.append("callback);").softNewLine(); + writer.outdent().append("}").ws().append("catch($e)").ws().append("{").indent().softNewLine(); + writer.append("return $return($rt_asyncError($e));").softNewLine(); + writer.outdent().append("}").softNewLine(); + } + + private MethodReference getAsyncReference(MethodReference methodRef) { + ValueType[] signature = new ValueType[methodRef.parameterCount() + 2]; + for (int i = 0; i < methodRef.parameterCount(); ++i) { + signature[i] = methodRef.getDescriptor().parameterType(i); + } + signature[methodRef.parameterCount()] = ValueType.parse(AsyncCallback.class); + signature[methodRef.parameterCount() + 1] = ValueType.VOID; + return new MethodReference(methodRef.getClassName(), methodRef.getName(), signature); + } + + @Override + public void methodAchieved(DependencyAgent checker, MethodDependency method, CallLocation location) { + MethodReference asyncRef = getAsyncReference(method.getReference()); + MethodDependency asyncMethod = checker.linkMethod(asyncRef, location); + int paramCount = method.getReference().parameterCount(); + for (int i = 0; i <= paramCount; ++i) { + method.getVariable(i).connect(asyncMethod.getVariable(i)); + } + asyncMethod.use(); + } +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java new file mode 100644 index 000000000..9bc0b6564 --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java @@ -0,0 +1,61 @@ +/* + * Copyright 2015 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.platform.plugin; + +import org.teavm.dependency.PluggableDependency; +import org.teavm.diagnostics.Diagnostics; +import org.teavm.javascript.spi.Async; +import org.teavm.javascript.spi.GeneratedBy; +import org.teavm.model.*; +import org.teavm.platform.async.AsyncCallback; + +/** + * + * @author Alexey Andreev + */ +public class AsyncMethodProcessor implements ClassHolderTransformer { + @Override + public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) { + for (MethodHolder method : cls.getMethods()) { + if (method.hasModifier(ElementModifier.NATIVE) && + method.getAnnotations().get(Async.class.getName()) != null && + method.getAnnotations().get(GeneratedBy.class.getName()) == null) { + ValueType[] signature = new ValueType[method.parameterCount() + 2]; + for (int i = 0; i < method.parameterCount(); ++i) { + signature[i] = method.parameterType(i); + } + signature[method.parameterCount()] = ValueType.parse(AsyncCallback.class); + signature[method.parameterCount() + 1] = ValueType.VOID; + MethodDescriptor asyncDesc = new MethodDescriptor(method.getName(), signature); + MethodHolder asyncMethod = cls.getMethod(asyncDesc); + if (asyncMethod != null) { + if (asyncMethod.hasModifier(ElementModifier.STATIC) != + method.hasModifier(ElementModifier.STATIC)) { + diagnostics.error(new CallLocation(method.getReference()), "Methods {{m0}} and {{m1}} must " + + "both be either static or non-static", + method.getReference(), asyncMethod.getReference()); + } + AnnotationHolder annot = new AnnotationHolder(GeneratedBy.class.getName()); + annot.getValues().put("value", new AnnotationValue(ValueType.parse(AsyncMethodGenerator.class))); + method.getAnnotations().add(annot); + annot = new AnnotationHolder(PluggableDependency.class.getName()); + annot.getValues().put("value", new AnnotationValue(ValueType.parse(AsyncMethodGenerator.class))); + method.getAnnotations().add(annot); + } + } + } + } +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeClassResource.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeClassResource.java new file mode 100644 index 000000000..2e9ac00dd --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeClassResource.java @@ -0,0 +1,41 @@ +/* + * Copyright 2015 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.platform.plugin; + +import java.io.IOException; +import org.teavm.codegen.SourceWriter; +import org.teavm.platform.metadata.ClassResource; + +/** + * + * @author Alexey Andreev + */ +class BuildTimeClassResource implements ClassResource, ResourceWriter { + private String className; + + public BuildTimeClassResource(String className) { + this.className = className; + } + + public String getClassName() { + return className; + } + + @Override + public void write(SourceWriter writer) throws IOException { + writer.appendClass(className); + } +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceProxyBuilder.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceProxyBuilder.java index a936fee0f..a1cda00fd 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceProxyBuilder.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceProxyBuilder.java @@ -102,8 +102,8 @@ class BuildTimeResourceProxyBuilder { private void scanIface(Class iface) { if (!Resource.class.isAssignableFrom(iface)) { - throw new IllegalArgumentException("Error creating a new resource of type " + iface.getName() + - ". This type does not implement the " + Resource.class.getName() + " interface"); + throw new IllegalArgumentException("Error creating a new resource of type " + iface.getName() + "." + + " This type does not implement the " + Resource.class.getName() + " interface"); } // Scan methods diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceWriterMethod.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceWriterMethod.java index dead2901c..b24c0547d 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceWriterMethod.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/BuildTimeResourceWriterMethod.java @@ -36,7 +36,7 @@ class BuildTimeResourceWriterMethod implements BuildTimeResourceMethod { if (i > 0) { writer.append(',').ws(); } - ResourceWriterHelper.writeString(writer, propertyNames[i]); + ResourceWriterHelper.writeIdentifier(writer, propertyNames[i]); writer.ws().append(':').ws(); ResourceWriterHelper.write(writer, proxy.data[i]); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/ClassLookupDependencySupport.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/ClassLookupDependencySupport.java similarity index 90% rename from teavm-classlib/src/main/java/org/teavm/classlib/impl/ClassLookupDependencySupport.java rename to teavm-platform/src/main/java/org/teavm/platform/plugin/ClassLookupDependencySupport.java index 4d4238300..a57d59b02 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/ClassLookupDependencySupport.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/ClassLookupDependencySupport.java @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.classlib.impl; +package org.teavm.platform.plugin; import org.teavm.dependency.*; import org.teavm.model.*; +import org.teavm.platform.Platform; /** * @@ -38,14 +39,14 @@ public class ClassLookupDependencySupport implements DependencyListener { @Override public void methodAchieved(final DependencyAgent agent, MethodDependency method, final CallLocation location) { MethodReference ref = method.getReference(); - if (ref.getClassName().equals("java.lang.Class") && ref.getName().equals("forNameImpl")) { + if (ref.getClassName().equals(Platform.class.getName()) && ref.getName().equals("lookupClass")) { allClasses.addConsumer(new DependencyConsumer() { @Override public void consume(DependencyAgentType type) { ClassReader cls = agent.getClassSource().get(type.getName()); if (cls == null) { return; } - MethodReader initMethod = cls.getMethod(new MethodDescriptor("", ValueType.VOID)); + MethodReader initMethod = cls.getMethod(new MethodDescriptor("", void.class)); if (initMethod != null) { agent.linkMethod(initMethod.getReference(), location).use(); } diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/ClassScopedMetadataProviderNativeGenerator.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/ClassScopedMetadataProviderNativeGenerator.java new file mode 100644 index 000000000..eef273ead --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/ClassScopedMetadataProviderNativeGenerator.java @@ -0,0 +1,97 @@ +/* + * Copyright 2015 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.platform.plugin; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; +import org.teavm.codegen.SourceWriter; +import org.teavm.javascript.Renderer; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; +import org.teavm.model.*; +import org.teavm.platform.metadata.ClassScopedMetadataGenerator; +import org.teavm.platform.metadata.ClassScopedMetadataProvider; +import org.teavm.platform.metadata.Resource; + +/** + * + * @author Alexey Andreev + */ +public class ClassScopedMetadataProviderNativeGenerator implements Generator { + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { + // Validate method + ClassReader cls = context.getClassSource().get(methodRef.getClassName()); + MethodReader method = cls.getMethod(methodRef.getDescriptor()); + AnnotationReader providerAnnot = method.getAnnotations().get(ClassScopedMetadataProvider.class.getName()); + if (providerAnnot == null) { + return; + } + if (!method.hasModifier(ElementModifier.NATIVE)) { + context.getDiagnostics().error(new CallLocation(methodRef), "Method {{m0}} is marked with " + + "{{c1}} annotation, but it is not native", methodRef, ClassScopedMetadataProvider.class.getName()); + return; + } + + // Find and instantiate metadata generator + ValueType generatorType = providerAnnot.getValue("value").getJavaClass(); + String generatorClassName = ((ValueType.Object)generatorType).getClassName(); + Class generatorClass; + try { + generatorClass = Class.forName(generatorClassName, true, context.getClassLoader()); + } catch (ClassNotFoundException e) { + context.getDiagnostics().error(new CallLocation(methodRef), "Can't find metadata provider class {{c0}}", + generatorClassName); + return; + } + Constructor cons; + try { + cons = generatorClass.getConstructor(); + } catch (NoSuchMethodException e) { + context.getDiagnostics().error(new CallLocation(methodRef), "Metadata generator {{c0}} does not have " + + "a public no-arg constructor", generatorClassName); + return; + } + ClassScopedMetadataGenerator generator; + try { + generator = (ClassScopedMetadataGenerator)cons.newInstance(); + } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) { + context.getDiagnostics().error(new CallLocation(methodRef), "Error instantiating metadata " + + "generator {{c0}}", generatorClassName); + return; + } + DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(), + context.getClassLoader(), context.getProperties(), context); + + Map resourceMap = generator.generateMetadata(metadataContext, methodRef); + writer.append("var p").ws().append("=").ws().append("\"" + Renderer.escapeString("$$res_" + + writer.getNaming().getNameFor(methodRef)) + "\"").append(";").softNewLine(); + for (Map.Entry entry : resourceMap.entrySet()) { + writer.appendClass(entry.getKey()).append("[p]").ws().append("=").ws(); + ResourceWriterHelper.write(writer, entry.getValue()); + writer.append(";").softNewLine(); + } + writer.appendMethodBody(methodRef).ws().append('=').ws().append("function(cls)").ws().append("{") + .softNewLine().indent(); + writer.append("return cls.hasOwnProperty(p)").ws().append("?").ws().append("cls[p]").ws().append(":") + .ws().append("null;").softNewLine(); + writer.outdent().append("}").softNewLine(); + writer.append("return ").appendMethodBody(methodRef).append("(").append(context.getParameterName(1)) + .append(");").softNewLine(); + } +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/DefaultMetadataGeneratorContext.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/DefaultMetadataGeneratorContext.java index 947202715..049fe912b 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/DefaultMetadataGeneratorContext.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/DefaultMetadataGeneratorContext.java @@ -19,10 +19,7 @@ import java.lang.reflect.Proxy; import java.util.Properties; import org.teavm.common.ServiceRepository; import org.teavm.model.ListableClassReaderSource; -import org.teavm.platform.metadata.MetadataGeneratorContext; -import org.teavm.platform.metadata.Resource; -import org.teavm.platform.metadata.ResourceArray; -import org.teavm.platform.metadata.ResourceMap; +import org.teavm.platform.metadata.*; /** * @@ -70,6 +67,11 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext { return new BuildTimeResourceArray<>(); } + @Override + public ClassResource createClassResource(String className) { + return new BuildTimeClassResource(className); + } + @Override public ResourceMap createResourceMap() { return new BuildTimeResourceMap<>(); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumDependencySupport.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/EnumDependencySupport.java similarity index 93% rename from teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumDependencySupport.java rename to teavm-platform/src/main/java/org/teavm/platform/plugin/EnumDependencySupport.java index 190defd64..fe0deb778 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumDependencySupport.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/EnumDependencySupport.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.classlib.impl; +package org.teavm.platform.plugin; import org.teavm.dependency.*; import org.teavm.model.CallLocation; @@ -21,6 +21,7 @@ import org.teavm.model.ClassReader; import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodReader; import org.teavm.model.ValueType; +import org.teavm.platform.Platform; /** * @@ -53,8 +54,8 @@ public class EnumDependencySupport implements DependencyListener { @Override public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) { - if (method.getReference().getClassName().equals("java.lang.Class") && - method.getReference().getName().equals("getEnumConstantsImpl")) { + if (method.getReference().getClassName().equals(Platform.class.getName()) && + method.getReference().getName().equals("getEnumConstants")) { unlocked = true; allEnums.connect(method.getResult().getArrayItem()); method.getResult().propagate(agent.getType("[java.lang.Enum")); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumTransformer.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/EnumTransformer.java similarity index 93% rename from teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumTransformer.java rename to teavm-platform/src/main/java/org/teavm/platform/plugin/EnumTransformer.java index 4f6355827..4be7e36a0 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/EnumTransformer.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/EnumTransformer.java @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.classlib.impl; +package org.teavm.platform.plugin; import org.teavm.diagnostics.Diagnostics; -import org.teavm.javascript.ni.PreserveOriginalName; +import org.teavm.javascript.spi.PreserveOriginalName; import org.teavm.model.*; /** diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderNativeGenerator.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderNativeGenerator.java index 6ddda44ca..3d44de603 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderNativeGenerator.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderNativeGenerator.java @@ -19,8 +19,8 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.teavm.codegen.SourceWriter; -import org.teavm.javascript.ni.Generator; -import org.teavm.javascript.ni.GeneratorContext; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; import org.teavm.model.*; import org.teavm.platform.metadata.MetadataGenerator; import org.teavm.platform.metadata.MetadataProvider; @@ -41,8 +41,9 @@ public class MetadataProviderNativeGenerator implements Generator { return; } if (!method.hasModifier(ElementModifier.NATIVE)) { - throw new IllegalStateException("Method " + method.getReference() + " was marked with " + - MetadataProvider.class.getName() + " but it is not native"); + context.getDiagnostics().error(new CallLocation(methodRef), "Method {{m0}} is marked with " + + "{{c1}} annotation, but it is not native", methodRef, MetadataProvider.class.getName()); + return; } // Find and instantiate metadata generator @@ -52,23 +53,25 @@ public class MetadataProviderNativeGenerator implements Generator { try { generatorClass = Class.forName(generatorClassName, true, context.getClassLoader()); } catch (ClassNotFoundException e) { - throw new RuntimeException("Can't find metadata generator class: " + generatorClassName, e); + context.getDiagnostics().error(new CallLocation(methodRef), "Can't find metadata provider class {{c0}}", + generatorClassName); + return; } Constructor cons; try { cons = generatorClass.getConstructor(); } catch (NoSuchMethodException e) { - throw new RuntimeException("Metadata generator " + generatorClassName + " does not have a public " + - "no-arg constructor", e); + context.getDiagnostics().error(new CallLocation(methodRef), "Metadata generator {{c0}} does not have " + + "a public no-arg constructor", generatorClassName); + return; } MetadataGenerator generator; try { generator = (MetadataGenerator)cons.newInstance(); - } catch (IllegalAccessException | InstantiationException e) { - throw new RuntimeException("Error instantiating metadata generator " + generatorClassName, e); - } catch (InvocationTargetException e) { - throw new RuntimeException("Error instantiating metadata generator " + generatorClassName, - e.getTargetException()); + } catch (IllegalAccessException | InstantiationException | InvocationTargetException e) { + context.getDiagnostics().error(new CallLocation(methodRef), "Error instantiating metadata " + + "generator {{c0}}", generatorClassName); + return; } DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(), context.getClassLoader(), context.getProperties(), context); diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java index 3ad502b9e..0bf498544 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java @@ -16,8 +16,10 @@ package org.teavm.platform.plugin; import org.teavm.diagnostics.Diagnostics; -import org.teavm.javascript.ni.GeneratedBy; +import org.teavm.javascript.spi.GeneratedBy; import org.teavm.model.*; +import org.teavm.platform.PlatformClass; +import org.teavm.platform.metadata.ClassScopedMetadataProvider; import org.teavm.platform.metadata.MetadataProvider; /** @@ -29,13 +31,26 @@ class MetadataProviderTransformer implements ClassHolderTransformer { public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) { for (MethodHolder method : cls.getMethods()) { AnnotationReader providerAnnot = method.getAnnotations().get(MetadataProvider.class.getName()); - if (providerAnnot == null) { - continue; + if (providerAnnot != null) { + AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName()); + genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( + MetadataProviderNativeGenerator.class.getName()))); + method.getAnnotations().add(genAnnot); + } + providerAnnot = method.getAnnotations().get(ClassScopedMetadataProvider.class.getName()); + if (providerAnnot != null) { + ValueType[] params = method.getParameterTypes(); + if (params.length != 1 && params[0].isObject(PlatformClass.class.getName())) { + diagnostics.error(new CallLocation(method.getReference()), "Method {{m0}} marked with {{c1}} " + + "must take exactly one parameter of type {{c2}}", + method.getReference(), ClassScopedMetadataProvider.class.getName(), + PlatformClass.class.getName()); + } + AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName()); + genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( + ClassScopedMetadataProviderNativeGenerator.class.getName()))); + method.getAnnotations().add(genAnnot); } - AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName()); - genAnnot.getValues().put("value", new AnnotationValue(ValueType.object( - MetadataProviderNativeGenerator.class.getName()))); - method.getAnnotations().add(genAnnot); } } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/NewInstanceDependencySupport.java similarity index 83% rename from teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java rename to teavm-platform/src/main/java/org/teavm/platform/plugin/NewInstanceDependencySupport.java index e94490899..14897e80b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/NewInstanceDependencySupport.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/NewInstanceDependencySupport.java @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.teavm.classlib.impl; +package org.teavm.platform.plugin; import org.teavm.dependency.*; import org.teavm.model.*; +import org.teavm.platform.Platform; /** * @@ -39,7 +40,7 @@ public class NewInstanceDependencySupport implements DependencyListener { if (cls.hasModifier(ElementModifier.ABSTRACT) || cls.hasModifier(ElementModifier.INTERFACE)) { return; } - MethodReader method = cls.getMethod(new MethodDescriptor("", ValueType.VOID)); + MethodReader method = cls.getMethod(new MethodDescriptor("", void.class)); if (method != null) { allClassesNode.propagate(agent.getType(className)); } @@ -48,7 +49,7 @@ public class NewInstanceDependencySupport implements DependencyListener { @Override public void methodAchieved(final DependencyAgent agent, MethodDependency method, final CallLocation location) { MethodReader reader = method.getMethod(); - if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) { + if (reader.getOwnerName().equals(Platform.class.getName()) && reader.getName().equals("newInstance")) { allClassesNode.connect(method.getResult()); method.getResult().addConsumer(new DependencyConsumer() { @Override public void consume(DependencyAgentType type) { @@ -59,8 +60,10 @@ public class NewInstanceDependencySupport implements DependencyListener { } private void attachConstructor(DependencyAgent checker, String type, CallLocation location) { - MethodReference ref = new MethodReference(type, new MethodDescriptor("", ValueType.VOID)); - checker.linkMethod(ref, location).use(); + MethodReference ref = new MethodReference(type, "", ValueType.VOID); + MethodDependency methodDep = checker.linkMethod(ref, location); + methodDep.getVariable(0).propagate(checker.getType(type)); + methodDep.use(); } @Override diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java new file mode 100644 index 000000000..5d812c02f --- /dev/null +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformGenerator.java @@ -0,0 +1,120 @@ +/* + * Copyright 2015 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.platform.plugin; + +import java.io.IOException; +import org.teavm.codegen.SourceWriter; +import org.teavm.dependency.DependencyAgent; +import org.teavm.dependency.DependencyPlugin; +import org.teavm.dependency.MethodDependency; +import org.teavm.javascript.spi.Generator; +import org.teavm.javascript.spi.GeneratorContext; +import org.teavm.javascript.spi.Injector; +import org.teavm.javascript.spi.InjectorContext; +import org.teavm.model.*; + +/** + * + * @author Alexey Andreev + */ +public class PlatformGenerator implements Generator, Injector, DependencyPlugin { + @Override + public void methodAchieved(DependencyAgent agent, MethodDependency method, CallLocation location) { + switch (method.getReference().getName()) { + case "asJavaClass": + method.getResult().propagate(agent.getType("java.lang.Class")); + return; + case "clone": + method.getVariable(0).connect(method.getResult()); + break; + } + } + + @Override + public void generate(InjectorContext context, MethodReference methodRef) throws IOException { + switch (methodRef.getName()) { + case "asJavaClass": + case "classFromResource": + context.writeExpr(context.getArgument(0)); + return; + case "getEnumConstants": + context.writeExpr(context.getArgument(0)); + context.getWriter().append(".values()"); + break; + } + } + + @Override + public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException { + switch (methodRef.getName()) { + case "newInstance": + generateNewInstance(context, writer, methodRef); + break; + case "lookupClass": + generateLookup(context, writer); + break; + case "clone": + generateClone(context, writer); + break; + } + } + + private void generateNewInstance(GeneratorContext context, SourceWriter writer, MethodReference methodRef) + throws IOException { + writer.append("var c").ws().append("=").ws().append("'$$constructor$$';").softNewLine(); + for (String clsName : context.getClassSource().getClassNames()) { + ClassReader cls = context.getClassSource().get(clsName); + MethodReader method = cls.getMethod(new MethodDescriptor("", void.class)); + if (method != null) { + writer.appendClass(clsName).append("[c]").ws().append("=").ws() + .append(writer.getNaming().getNameForInit(method.getReference())) + .append(";").softNewLine(); + } + } + writer.appendMethodBody(methodRef).ws().append("=").ws().append("function(cls)").ws().append("{") + .softNewLine().indent(); + writer.append("if").ws().append("(!cls.hasOwnProperty(c))").ws().append("{").indent().softNewLine(); + writer.append("return null;").softNewLine(); + writer.outdent().append("}").softNewLine(); + writer.append("return cls[c]();").softNewLine(); + writer.outdent().append("}").softNewLine(); + writer.append("return ").appendMethodBody(methodRef).append("(") + .append(context.getParameterName(1)).append(");").softNewLine(); + } + + private void generateLookup(GeneratorContext context, SourceWriter writer) throws IOException { + String param = context.getParameterName(1); + writer.append("switch ($rt_ustr(" + param + ")) {").softNewLine().indent(); + for (String name : context.getClassSource().getClassNames()) { + writer.append("case \"" + name + "\": ").appendClass(name).append(".$clinit(); ") + .append("return ").appendClass(name).append(";").softNewLine(); + } + writer.append("default: return null;").softNewLine(); + writer.outdent().append("}").softNewLine(); + } + + private void generateClone(GeneratorContext context, SourceWriter writer) throws IOException { + String obj = context.getParameterName(1); + writer.append("var copy").ws().append("=").ws().append("new ").append(obj).append(".constructor();") + .softNewLine(); + writer.append("for").ws().append("(var field in " + obj + ")").ws().append("{").softNewLine().indent(); + writer.append("if").ws().append("(!" + obj + ".hasOwnProperty(field))").ws().append("{").softNewLine().indent(); + writer.append("continue;").softNewLine().outdent().append("}").softNewLine(); + writer.append("copy[field]").ws().append("=").ws().append(obj).append("[field];") + .softNewLine().outdent().append("}").softNewLine(); + writer.append("return copy;").softNewLine(); + } +} diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java index ad16bfc25..710e0c718 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/PlatformPlugin.java @@ -29,5 +29,10 @@ public class PlatformPlugin implements TeaVMPlugin { host.add(new ResourceTransformer()); host.add(new ResourceAccessorTransformer(host)); host.add(new ResourceAccessorDependencyListener()); + host.add(new AsyncMethodProcessor()); + host.add(new NewInstanceDependencySupport()); + host.add(new ClassLookupDependencySupport()); + host.add(new EnumDependencySupport()); + host.add(new EnumTransformer()); } } diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorGenerator.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorGenerator.java index 62c267ad5..18337035c 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorGenerator.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceAccessorGenerator.java @@ -18,8 +18,8 @@ package org.teavm.platform.plugin; import java.io.IOException; import org.teavm.javascript.ast.ConstantExpr; import org.teavm.javascript.ast.Expr; -import org.teavm.javascript.ni.Injector; -import org.teavm.javascript.ni.InjectorContext; +import org.teavm.javascript.spi.Injector; +import org.teavm.javascript.spi.InjectorContext; import org.teavm.model.MethodReference; import org.teavm.model.ValueType; diff --git a/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceWriterHelper.java b/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceWriterHelper.java index af816217f..715d248ba 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceWriterHelper.java +++ b/teavm-platform/src/main/java/org/teavm/platform/plugin/ResourceWriterHelper.java @@ -45,6 +45,34 @@ final class ResourceWriterHelper { } } + public static void writeIdentifier(SourceWriter writer, String id) throws IOException { + if (id.isEmpty() || !isIdentifierStart(id.charAt(0))) { + writeString(writer, id); + return; + } + for (int i = 1; i < id.length(); ++i) { + if (isIdentifierPart(id.charAt(i))) { + writeString(writer, id); + return; + } + } + writer.append(id); + } + + private static boolean isIdentifierStart(char c) { + if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') { + return true; + } + return c == '$' || c == '_'; + } + + private static boolean isIdentifierPart(char c) { + if (isIdentifierStart(c)) { + return true; + } + return c >= '0' && c <= '9'; + } + public static void writeString(SourceWriter writer, String s) throws IOException { writer.append('"'); for (int i = 0; i < s.length(); ++i) { diff --git a/teavm-samples/teavm-samples-benchmark/pom.xml b/teavm-samples/teavm-samples-benchmark/pom.xml index 711bcca06..bbf7e22d0 100644 --- a/teavm-samples/teavm-samples-benchmark/pom.xml +++ b/teavm-samples/teavm-samples-benchmark/pom.xml @@ -91,7 +91,7 @@ ${project.build.directory}/generated/js/teavm org.teavm.samples.benchmark.teavm.BenchmarkStarter SEPARATE - false + true true diff --git a/teavm-tests/.gitignore b/teavm-tests/.gitignore new file mode 100644 index 000000000..c708c363d --- /dev/null +++ b/teavm-tests/.gitignore @@ -0,0 +1,4 @@ +/target +/.settings +/.classpath +/.project diff --git a/teavm-tests/pom.xml b/teavm-tests/pom.xml new file mode 100644 index 000000000..806173c02 --- /dev/null +++ b/teavm-tests/pom.xml @@ -0,0 +1,115 @@ + + + 4.0.0 + + + org.teavm + teavm + 0.3.0-SNAPSHOT + + teavm-tests + + TeaVM tests + Project containing TeaVM tests, as it is impossible to test each module separately + + + + org.teavm + teavm-core + ${project.version} + + + org.teavm + teavm-classlib + ${project.version} + + + org.teavm + teavm-platform + ${project.version} + + + org.teavm + teavm-jso + ${project.version} + + + junit + junit + test + + + + + + + org.teavm + teavm-maven-plugin + ${project.version} + + + org.teavm + teavm-platform + ${project.version} + + + + + generate-javascript-tests + + build-test-javascript + + process-test-classes + + false + + en, en_US, en_GB, ru, ru_RU + + ${teavm.test.incremental} + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org/teavm/platform/**/*.java + org/teavm/jso/**/*.java + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ../checkstyle.xml + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + \ No newline at end of file diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/io/BufferedInputStreamTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/io/BufferedInputStreamTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/io/BufferedInputStreamTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/io/BufferedInputStreamTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/io/BufferedReaderTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/io/BufferedReaderTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/io/BufferedReaderTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/io/BufferedReaderTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/io/InputStreamReaderTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/io/InputStreamReaderTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/io/InputStreamReaderTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/io/InputStreamReaderTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/io/PushbackInputStreamTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/io/PushbackInputStreamTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/io/PushbackInputStreamTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/io/PushbackInputStreamTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/BooleanTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/BooleanTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/BooleanTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/BooleanTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/CharacterTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/CharacterTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/CharacterTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/CharacterTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ClassTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/ClassTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ClassTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/ClassTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/DoubleTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/DoubleTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/DoubleTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/DoubleTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/EnumTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/EnumTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/EnumTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/EnumTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/FloatTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/FloatTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/FloatTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/FloatTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/IntegerTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/IntegerTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/IntegerTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/IntegerTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/MathTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/MathTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/MathTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/MathTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ObjectTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/ObjectTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ObjectTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/ObjectTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/StringBuilderTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/StringBuilderTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/StringBuilderTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/StringBuilderTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/StringTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/StringTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/StringTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/StringTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/SystemTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/SystemTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/SystemTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/SystemTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/TestObject.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/TestObject.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/TestObject.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/TestObject.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ThreadTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/ThreadTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/ThreadTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/ThreadTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/VMTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/VMTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/VMTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/VMTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/reflect/ArrayTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/lang/reflect/ArrayTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/lang/reflect/ArrayTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/lang/reflect/ArrayTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalArithmeticTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalArithmeticTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalArithmeticTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalArithmeticTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalCompareTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalCompareTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalCompareTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalCompareTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalConstructorsTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalConstructorsTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalConstructorsTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalConstructorsTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalConvertTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalConvertTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalConvertTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalConvertTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalScaleOperationsTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalScaleOperationsTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigDecimalScaleOperationsTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigDecimalScaleOperationsTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerAddTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerAddTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerAddTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerAddTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerAndTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerAndTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerAndTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerAndTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerCompareTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerCompareTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerCompareTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerCompareTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerConstructorsTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerConstructorsTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerConstructorsTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerConstructorsTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerConvertTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerConvertTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerConvertTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerConvertTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerDivideTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerDivideTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerDivideTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerDivideTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerHashCodeTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerHashCodeTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerHashCodeTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerHashCodeTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerModPowTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerModPowTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerModPowTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerModPowTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerMultiplyTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerMultiplyTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerMultiplyTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerMultiplyTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerNotTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerNotTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerNotTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerNotTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerOperateBitsTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerOperateBitsTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerOperateBitsTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerOperateBitsTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerOrTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerOrTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerOrTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerOrTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerSubtractTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerSubtractTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerSubtractTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerSubtractTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerToStringTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerToStringTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerToStringTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerToStringTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerXorTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerXorTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/math/BigIntegerXorTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/math/BigIntegerXorTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/nio/ByteBufferTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/ByteBufferTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/nio/ByteBufferTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/nio/ByteBufferTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/nio/ByteBufferWrapperTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/ByteBufferWrapperTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/nio/ByteBufferWrapperTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/nio/ByteBufferWrapperTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/nio/CharBufferTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/CharBufferTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/nio/CharBufferTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/nio/CharBufferTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/nio/DoubleBufferTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/DoubleBufferTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/nio/DoubleBufferTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/nio/DoubleBufferTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/nio/FloatBufferTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/FloatBufferTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/nio/FloatBufferTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/nio/FloatBufferTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/nio/IntBufferTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/IntBufferTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/nio/IntBufferTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/nio/IntBufferTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/nio/LongBufferTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/LongBufferTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/nio/LongBufferTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/nio/LongBufferTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/nio/ShortBufferTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/nio/ShortBufferTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/nio/ShortBufferTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/nio/ShortBufferTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/text/DateFormatTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/text/DateFormatTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/text/DateFormatTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/text/DateFormatTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/text/SimpleDateFormatTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/text/SimpleDateFormatTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/text/SimpleDateFormatTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/text/SimpleDateFormatTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/ArrayDequeTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/ArrayDequeTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/ArrayDequeTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/ArrayDequeTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/ArrayListTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/ArrayListTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/ArrayListTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/ArrayListTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/ArraysTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/ArraysTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/ArraysTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/BitSetTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/BitSetTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/BitSetTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/BitSetTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/CollectionsTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/CollectionsTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/CollectionsTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/CollectionsTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/HashtableTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/HashtableTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/HashtableTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/HashtableTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/LinkedHashMapTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/LinkedHashMapTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/LinkedHashMapTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/LinkedHashMapTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/LinkedListTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/LinkedListTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/LinkedListTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/LinkedListTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/LocaleTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/LocaleTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/LocaleTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/LocaleTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/PriorityQueueTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/PriorityQueueTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/PriorityQueueTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/PriorityQueueTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/ServiceLoaderTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/ServiceLoaderTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/ServiceLoaderTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/ServiceLoaderTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/StringTokenizerTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/StringTokenizerTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/StringTokenizerTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/StringTokenizerTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/TestService.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/TestService.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/TestService.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/TestService.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/TestServiceImpl.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/TestServiceImpl.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/TestServiceImpl.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/TestServiceImpl.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/TreeMapTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/TreeMapTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/TreeMapTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/TreeMapTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/VectorTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/VectorTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/VectorTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/VectorTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/Matcher2Test.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/Matcher2Test.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/Matcher2Test.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/Matcher2Test.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/MatcherTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/MatcherTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/MatcherTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/MatcherTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/ModeTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/ModeTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/ModeTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/ModeTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/Pattern2Test.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/Pattern2Test.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/Pattern2Test.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/Pattern2Test.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/PatternErrorTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/PatternErrorTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/PatternErrorTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/PatternErrorTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/PatternSyntaxExceptionTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/PatternSyntaxExceptionTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/PatternSyntaxExceptionTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/PatternSyntaxExceptionTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/PatternTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/PatternTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/PatternTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/PatternTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/ReplaceTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/ReplaceTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/ReplaceTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/ReplaceTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/SplitTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/SplitTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/regex/SplitTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/regex/SplitTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/util/zip/GZIPInputStreamTest.java b/teavm-tests/src/test/java/org/teavm/classlib/java/util/zip/GZIPInputStreamTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/java/util/zip/GZIPInputStreamTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/java/util/zip/GZIPInputStreamTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/support/Support_CollectionTest.java b/teavm-tests/src/test/java/org/teavm/classlib/support/Support_CollectionTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/support/Support_CollectionTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/support/Support_CollectionTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/support/Support_ListTest.java b/teavm-tests/src/test/java/org/teavm/classlib/support/Support_ListTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/support/Support_ListTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/support/Support_ListTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/support/Support_MapTest2.java b/teavm-tests/src/test/java/org/teavm/classlib/support/Support_MapTest2.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/support/Support_MapTest2.java rename to teavm-tests/src/test/java/org/teavm/classlib/support/Support_MapTest2.java diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/support/Support_UnmodifiableCollectionTest.java b/teavm-tests/src/test/java/org/teavm/classlib/support/Support_UnmodifiableCollectionTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/classlib/support/Support_UnmodifiableCollectionTest.java rename to teavm-tests/src/test/java/org/teavm/classlib/support/Support_UnmodifiableCollectionTest.java diff --git a/teavm-jso/src/test/java/org/teavm/jso/test/JSOTest.java b/teavm-tests/src/test/java/org/teavm/jso/test/JSOTest.java similarity index 100% rename from teavm-jso/src/test/java/org/teavm/jso/test/JSOTest.java rename to teavm-tests/src/test/java/org/teavm/jso/test/JSOTest.java diff --git a/teavm-jso/src/test/java/org/teavm/jso/test/RegExp.java b/teavm-tests/src/test/java/org/teavm/jso/test/RegExp.java similarity index 100% rename from teavm-jso/src/test/java/org/teavm/jso/test/RegExp.java rename to teavm-tests/src/test/java/org/teavm/jso/test/RegExp.java diff --git a/teavm-jso/src/test/java/org/teavm/jso/test/Window.java b/teavm-tests/src/test/java/org/teavm/jso/test/Window.java similarity index 100% rename from teavm-jso/src/test/java/org/teavm/jso/test/Window.java rename to teavm-tests/src/test/java/org/teavm/jso/test/Window.java diff --git a/teavm-classlib/src/test/java/org/teavm/platform/metadata/DependentTestResource.java b/teavm-tests/src/test/java/org/teavm/platform/metadata/DependentTestResource.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/platform/metadata/DependentTestResource.java rename to teavm-tests/src/test/java/org/teavm/platform/metadata/DependentTestResource.java diff --git a/teavm-classlib/src/test/java/org/teavm/platform/metadata/MetadataGeneratorTest.java b/teavm-tests/src/test/java/org/teavm/platform/metadata/MetadataGeneratorTest.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/platform/metadata/MetadataGeneratorTest.java rename to teavm-tests/src/test/java/org/teavm/platform/metadata/MetadataGeneratorTest.java diff --git a/teavm-classlib/src/test/java/org/teavm/platform/metadata/TestResource.java b/teavm-tests/src/test/java/org/teavm/platform/metadata/TestResource.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/platform/metadata/TestResource.java rename to teavm-tests/src/test/java/org/teavm/platform/metadata/TestResource.java diff --git a/teavm-classlib/src/test/java/org/teavm/platform/metadata/TestResourceGenerator.java b/teavm-tests/src/test/java/org/teavm/platform/metadata/TestResourceGenerator.java similarity index 100% rename from teavm-classlib/src/test/java/org/teavm/platform/metadata/TestResourceGenerator.java rename to teavm-tests/src/test/java/org/teavm/platform/metadata/TestResourceGenerator.java diff --git a/teavm-classlib/src/test/resources/META-INF/services/org.teavm.classlib.java.util.TestService b/teavm-tests/src/test/resources/META-INF/services/org.teavm.classlib.java.util.TestService similarity index 100% rename from teavm-classlib/src/test/resources/META-INF/services/org.teavm.classlib.java.util.TestService rename to teavm-tests/src/test/resources/META-INF/services/org.teavm.classlib.java.util.TestService