mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Start eliminating JavaScript generators in classlib in favour of calling
Platform and JSO
This commit is contained in:
parent
3b1d6851a4
commit
d93fa6cf41
|
@ -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.classlib.impl;
|
||||
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.platform.metadata.MetadataGenerator;
|
||||
import org.teavm.platform.metadata.MetadataGeneratorContext;
|
||||
import org.teavm.platform.metadata.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class DeclaringClassMetadataGenerator implements MetadataGenerator {
|
||||
@Override
|
||||
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -31,7 +31,6 @@ public class JCLPlugin implements TeaVMPlugin {
|
|||
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);
|
||||
|
|
|
@ -35,75 +35,18 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
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()");
|
||||
|
@ -111,24 +54,6 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
|
@ -140,32 +65,6 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
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("<init>", 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(
|
||||
"<init>", 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();
|
||||
|
@ -188,25 +87,10 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
@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, "<init>", void.class),
|
||||
location).use();
|
||||
|
|
|
@ -15,9 +15,11 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.javascript.spi.GeneratedBy;
|
||||
import org.teavm.classlib.impl.DeclaringClassMetadataGenerator;
|
||||
import org.teavm.javascript.spi.InjectedBy;
|
||||
import org.teavm.platform.Platform;
|
||||
import org.teavm.platform.PlatformClass;
|
||||
import org.teavm.platform.metadata.MetadataProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -25,102 +27,122 @@ import org.teavm.javascript.spi.InjectedBy;
|
|||
*/
|
||||
public class TClass<T> 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);
|
||||
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);
|
||||
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().isArray();
|
||||
}
|
||||
|
||||
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<TVoid> voidClass() {
|
||||
return (TClass<TVoid>)getClass(Platform.getPrimitives().getVoidClass());
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TVoid> voidClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TBoolean> booleanClass() {
|
||||
return (TClass<TBoolean>)getClass(Platform.getPrimitives().getBooleanClass());
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TBoolean> booleanClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TCharacter> charClass() {
|
||||
return (TClass<TCharacter>)getClass(Platform.getPrimitives().getCharClass());
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TCharacter> charClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TByte> byteClass() {
|
||||
return (TClass<TByte>)getClass(Platform.getPrimitives().getByteClass());
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TByte> byteClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TShort> shortClass() {
|
||||
return (TClass<TShort>)getClass(Platform.getPrimitives().getShortClass());
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TShort> shortClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TInteger> intClass() {
|
||||
return (TClass<TInteger>)getClass(Platform.getPrimitives().getIntClass());
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TInteger> intClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TLong> longClass() {
|
||||
return (TClass<TLong>)getClass(Platform.getPrimitives().getLongClass());
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TLong> longClass();
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TFloat> floatClass() {
|
||||
return (TClass<TFloat>)getClass(Platform.getPrimitives().getFloatClass());
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TFloat> floatClass();
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
static native TClass<TDouble> doubleClass();
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
public static native <S extends TObject> TClass<S> wrapClass(Class<S> cls);
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TDouble> doubleClass() {
|
||||
return (TClass<TDouble>)getClass(Platform.getPrimitives().getDoubleClass());
|
||||
}
|
||||
|
||||
public boolean desiredAssertionStatus() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
public native TClass<? super T> getSuperclass();
|
||||
@SuppressWarnings("unchecked")
|
||||
public TClass<? super T> getSuperclass() {
|
||||
return (TClass<? super T>)getClass(platformClass.getMetadata().getSuperclass());
|
||||
}
|
||||
|
||||
public T[] getEnumConstants() {
|
||||
return isEnum ? getEnumConstantsImpl() : null;
|
||||
return isEnum() ? getEnumConstantsImpl() : null;
|
||||
}
|
||||
|
||||
@InjectedBy(ClassNativeGenerator.class)
|
||||
|
@ -128,10 +150,9 @@ public class TClass<T> extends TObject {
|
|||
|
||||
@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,16 +161,12 @@ public class TClass<T> 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")
|
||||
|
@ -158,12 +175,11 @@ public class TClass<T> extends TObject {
|
|||
return forName(name);
|
||||
}
|
||||
|
||||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
public native T newInstance() throws TInstantiationException, TIllegalAccessException;
|
||||
public T newInstance() throws TInstantiationException, TIllegalAccessException {
|
||||
return Platform.newInstance(platformClass);
|
||||
}
|
||||
|
||||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
@PluggableDependency(ClassNativeGenerator.class)
|
||||
@MetadataProvider(DeclaringClassMetadataGenerator.class)
|
||||
public native TClass<?> getDeclaringClass();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
|
|
@ -61,7 +61,7 @@ public abstract class TEnum<E extends TEnum<E>> extends TObject implements TComp
|
|||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final TClass<E> getDeclaringClass() {
|
||||
return (TClass<E>)TClass.wrapClass(getClass());
|
||||
return (TClass<E>)(Object)getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -102,7 +102,7 @@ public final class JS {
|
|||
public static native JSObject wrap(short num);
|
||||
|
||||
@InjectedBy(JSNativeGenerator.class)
|
||||
public static native JSObject pass(Object obj);
|
||||
public static native JSObject marshall(Object obj);
|
||||
|
||||
public static <T extends JSObject> JSArray<T> wrap(T[] array) {
|
||||
JSArray<T> result = createArray(array.length);
|
||||
|
|
|
@ -35,6 +35,16 @@
|
|||
<artifactId>teavm-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-jso</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.teavm</groupId>
|
||||
<artifactId>teavm-dom</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* 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 <konsoletyper@gmail.com>
|
||||
*/
|
||||
public final class Platform {
|
||||
private Platform() {
|
||||
}
|
||||
|
||||
public static PlatformObject getPlatformObject(Object obj) {
|
||||
return (PlatformObject)JS.marshall(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<PlatformClass> 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();
|
||||
}
|
||||
|
||||
@GeneratedBy(PlatformGenerator.class)
|
||||
@PluggableDependency(PlatformGenerator.class)
|
||||
public static native <T> 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);
|
||||
|
||||
@GeneratedBy(PlatformGenerator.class)
|
||||
@PluggableDependency(PlatformGenerator.class)
|
||||
public static native PlatformClass classFromResource(ClassResource resource);
|
||||
}
|
|
@ -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;
|
||||
|
||||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.JSProperty;
|
||||
import org.teavm.platform.metadata.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface PlatformClass extends JSObject, Resource {
|
||||
@JSProperty("$meta")
|
||||
PlatformClassMetadata getMetadata();
|
||||
|
||||
@JSProperty("classObject")
|
||||
void setJavaClass(PlatformObject obj);
|
||||
|
||||
@JSProperty("classObject")
|
||||
PlatformObject getJavaClass();
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface PlatformClassMetadata extends JSObject {
|
||||
@JSProperty("item")
|
||||
PlatformClass getArrayItem();
|
||||
|
||||
@JSProperty
|
||||
PlatformSequence<PlatformClass> getSupertypes();
|
||||
|
||||
@JSProperty
|
||||
PlatformClass getSuperclass();
|
||||
|
||||
@JSProperty
|
||||
String getName();
|
||||
|
||||
@JSProperty
|
||||
boolean isPrimitive();
|
||||
|
||||
@JSProperty
|
||||
boolean isArray();
|
||||
|
||||
@JSProperty
|
||||
boolean isEnum();
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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 <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface PlatformObject extends JSObject {
|
||||
@JSProperty("constructor")
|
||||
PlatformClass getPlatformClass();
|
||||
}
|
|
@ -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.JSObject;
|
||||
import org.teavm.jso.JSProperty;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface PlatformPrimitives extends JSObject {
|
||||
@JSProperty("$rt_voidcls")
|
||||
PlatformClass getVoidClass();
|
||||
|
||||
@JSProperty("$rt_booleancls")
|
||||
PlatformClass getBooleanClass();
|
||||
|
||||
@JSProperty("$rt_bytecls")
|
||||
PlatformClass getByteClass();
|
||||
|
||||
@JSProperty("$rt_shortcls")
|
||||
PlatformClass getShortClass();
|
||||
|
||||
@JSProperty("$rt_charcls")
|
||||
PlatformClass getCharClass();
|
||||
|
||||
@JSProperty("$rt_intcls")
|
||||
PlatformClass getIntClass();
|
||||
|
||||
@JSProperty("$rt_longcls")
|
||||
PlatformClass getLongClass();
|
||||
|
||||
@JSProperty("$rt_floatcls")
|
||||
PlatformClass getFloatClass();
|
||||
|
||||
@JSProperty("$rt_doublecls")
|
||||
PlatformClass getDoubleClass();
|
||||
}
|
|
@ -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 <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface PlatformSequence<T> extends JSObject {
|
||||
@JSProperty
|
||||
int getLength();
|
||||
|
||||
@JSIndexer
|
||||
T get(int index);
|
||||
}
|
|
@ -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 <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface ClassResource extends Resource {
|
||||
}
|
|
@ -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 extends Resource> T createResource(Class<T> 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.
|
||||
*/
|
||||
|
|
|
@ -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 <konsoletyper@gmail.com>
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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 <T extends Resource> ResourceMap<T> createResourceMap() {
|
||||
return new BuildTimeResourceMap<>();
|
||||
|
|
|
@ -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("<init>", ValueType.VOID));
|
||||
MethodReader method = cls.getMethod(new MethodDescriptor("<init>", 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("<init>", ValueType.VOID));
|
||||
checker.linkMethod(ref, location).use();
|
||||
MethodReference ref = new MethodReference(type, "<init>", ValueType.VOID);
|
||||
MethodDependency methodDep = checker.linkMethod(ref, location);
|
||||
methodDep.getVariable(0).propagate(checker.getType(type));
|
||||
methodDep.use();
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.*;
|
||||
import org.teavm.platform.Platform;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "asJavaClass":
|
||||
context.writeExpr(context.getArgument(0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
switch (methodRef.getName()) {
|
||||
case "newInstance":
|
||||
generateNewInstance(context, writer);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateNewInstance(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||
String self = context.getParameterName(0);
|
||||
writer.append("if").ws().append("(!").appendClass(Platform.class).append(".$$constructors$$)").ws()
|
||||
.append("{").indent().softNewLine();
|
||||
writer.appendClass(Platform.class).append(".$$constructors$$").ws().append("=").append("true;").softNewLine();
|
||||
for (String clsName : context.getClassSource().getClassNames()) {
|
||||
ClassReader cls = context.getClassSource().get(clsName);
|
||||
MethodReader method = cls.getMethod(new MethodDescriptor("<init>", void.class));
|
||||
if (method != null) {
|
||||
writer.appendClass(clsName).append(".$$constructor$$").ws().append("=").ws()
|
||||
.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, "<init>", void.class))
|
||||
.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();
|
||||
}
|
||||
}
|
|
@ -30,5 +30,6 @@ public class PlatformPlugin implements TeaVMPlugin {
|
|||
host.add(new ResourceAccessorTransformer(host));
|
||||
host.add(new ResourceAccessorDependencyListener());
|
||||
host.add(new AsyncMethodProcessor());
|
||||
host.add(new NewInstanceDependencySupport());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user