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 index e1efe680a..86b7f8e9e 100644 --- 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 @@ -19,6 +19,9 @@ public class ClassNativeGenerator implements Generator { case "isAssignable": generateIsAssignableFrom(context, writer); break; + case "getComponentType": + generateGetComponentType(context, writer); + break; } } @@ -31,4 +34,10 @@ public class ClassNativeGenerator implements Generator { writer.append("return $rt_isAssignable(").append(context.getParameterName(1)).append(".$data, ") .append(context.getParameterName(0)).append(".$data;").newLine(); } + + private void generateGetComponentType(GeneratorContext context, SourceWriter writer) { + String thisArg = context.getParameterName(0); + writer.append("var item = " + thisArg + ".$data.$meta.item;").newLine(); + writer.append("return item != null ? $rt_cls(item) : null;").newLine(); + } } 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 index 9f10549a7..44e9b7d16 100644 --- 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 @@ -57,17 +57,7 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin { private void generateGetClass(GeneratorContext context, SourceWriter writer) { String thisArg = context.getParameterName(0); - String classClass = "java.lang.Class"; - writer.append("var cls = ").append(thisArg).append(".$class.classObject;").newLine(); - writer.append("if (cls === undefined) {").newLine().indent(); - MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew", - ValueType.object(classClass))); - writer.append("cls = ").appendClass(classClass).append('.').appendMethod(createMethodRef) - .append("();").newLine(); - writer.append("cls.$data = ").append(thisArg).append(".$class;").newLine(); - writer.append(thisArg).append(".$class.classObject = cls;").newLine(); - writer.outdent().append("}").newLine(); - writer.append("return cls;").newLine(); + writer.append("return $rt_cls(").append(thisArg).append(".$class);").newLine(); } private void achieveGetClass(DependencyChecker checker) { 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 6ec3d458c..1a6f1b1c4 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 @@ -7,10 +7,39 @@ import org.teavm.javascript.ni.GeneratedBy; * @author Alexey Andreev */ public class TClass extends TObject { + String name; + boolean primitive; + boolean array; + private TClass componentType; + private boolean componentTypeDirty = true; + static TClass createNew() { return new TClass<>(); } @GeneratedBy(ClassNativeGenerator.class) public native boolean isInstance(TObject obj); + + public String getName() { + return name; + } + + public boolean isPrimitive() { + return primitive; + } + + public boolean isArray() { + return array; + } + + public TClass getComponentType() { + if (componentTypeDirty) { + componentType = getComponentType0(); + componentTypeDirty = false; + } + return componentType; + } + + @GeneratedBy(ClassNativeGenerator.class) + private native TClass getComponentType0(); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassTests.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassTests.java new file mode 100644 index 000000000..6c73749b8 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TClassTests.java @@ -0,0 +1,30 @@ +package org.teavm.classlib.java.lang; + +import static org.junit.Assert.*; +import org.junit.Test; + +/** + * + * @author Alexey Andreev + */ +class TClassTests { + @Test + public void classNameEvaluated() { + assertEquals("java.lang.Object", Object.class.getName()); + } + + @Test + public void objectClassNameEvaluated() { + assertEquals("java.lang.Object", new Object().getClass().getName()); + } + + @Test + public void objectClassConsideredNotArray() { + assertFalse(Object.class.isArray()); + } + + @Test + public void arrayClassConsideredArray() { + assertFalse(Object[].class.isArray()); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlibgen/ClasslibTestGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlibgen/ClasslibTestGenerator.java index 8b592cad5..7ea8a2382 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlibgen/ClasslibTestGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlibgen/ClasslibTestGenerator.java @@ -32,7 +32,7 @@ public class ClasslibTestGenerator { private static List testMethods = new ArrayList<>(); private static Map> groupedMethods = new HashMap<>(); private static String[] testClasses = { "java.lang.ObjectTests", "java.lang.SystemTests", - "java.lang.StringBuilderTests" }; + "java.lang.StringBuilderTests", "java.lang.ClassTests" }; public static void main(String[] args) throws IOException { out = System.out; 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 5772bc1ca..106f76fd3 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -52,16 +52,28 @@ public class Renderer implements ExprVisitor, StatementVisitor { } private void renderRuntimeCls() { - writer.append("$rt_cls = function(cls) {").indent().newLine(); + writer.append("$rt_cls = function(clsProto) {").indent().newLine(); String classClass = "java.lang.Class"; - writer.append("var cls = cls.classObject;").newLine(); + writer.append("var cls = clsProto.classObject;").newLine(); writer.append("if (cls === undefined) {").newLine().indent(); MethodReference createMethodRef = new MethodReference(classClass, new MethodDescriptor("createNew", ValueType.object(classClass))); writer.append("cls = ").appendClass(classClass).append('.').appendMethod(createMethodRef) .append("();").newLine(); - writer.append("cls.$data = cls;").newLine(); - writer.append("cls.classObject = cls;").newLine(); + writer.append("cls.$data = clsProto;").newLine(); + if (classSource.getClassHolder(classClass).getField("name") != null) { + writer.append("cls.").appendField(new FieldReference(classClass, "name")) + .append(" = clsProto.$meta.name !== undefined ? $rt_str(clsProto.$meta.name) : null;").newLine(); + } + if (classSource.getClassHolder(classClass).getField("primitive") != null) { + writer.append("cls.").appendField(new FieldReference(classClass, "primitive")) + .append(" = clsProto.$meta.primitive ? 1 : 0;").newLine(); + } + if (classSource.getClassHolder(classClass).getField("array") != null) { + writer.append("cls.").appendField(new FieldReference(classClass, "array")) + .append(" = clsProto.$meta.item ? 1 : 0;").newLine(); + } + writer.append("clsProto.classObject = cls;").newLine(); writer.outdent().append("}").newLine(); writer.append("return cls;").newLine(); writer.outdent().append("}").newLine(); 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 44cf0a2c1..ea0971f17 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -50,7 +50,7 @@ $rt_arraycls = function(cls) { this.$class = arraycls; }; arraycls.prototype = new ($rt_objcls())(); - arraycls.$meta = { item : cls, supertypes : [$rt_objcls()] }; + arraycls.$meta = { item : cls, supertypes : [$rt_objcls()], primitive : false }; cls.$array = arraycls; } return cls.$array;