mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds simple support of Class.forName and class.newInstance
This commit is contained in:
parent
6e4e66c759
commit
9cdc099b1a
|
@ -27,5 +27,6 @@ public class JCLPlugin implements JavascriptBuilderPlugin {
|
|||
public void install(JavascriptBuilderHost host) {
|
||||
host.add(new EnumDependencySupport());
|
||||
host.add(new EnumTransformer());
|
||||
host.add(new NewInstanceDependencySupport());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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.impl;
|
||||
|
||||
import org.teavm.dependency.*;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class NewInstanceDependencySupport implements DependencyListener {
|
||||
private DependencyNode allClassesNode;
|
||||
|
||||
@Override
|
||||
public void started(DependencyChecker dependencyChecker) {
|
||||
allClassesNode = dependencyChecker.createNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void classAchieved(DependencyChecker dependencyChecker, String className) {
|
||||
ClassReader cls = dependencyChecker.getClassSource().get(className);
|
||||
if (cls.hasModifier(ElementModifier.ABSTRACT) || cls.hasModifier(ElementModifier.INTERFACE)) {
|
||||
return;
|
||||
}
|
||||
if (cls.getMethod(new MethodDescriptor("<init>", ValueType.VOID)) != null) {
|
||||
allClassesNode.propagate(className);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyChecker dependencyChecker, MethodDependency method) {
|
||||
MethodReader reader = method.getMethod();
|
||||
if (reader.getOwnerName().equals("java.lang.Class") && reader.getName().equals("newInstance")) {
|
||||
allClassesNode.connect(method.getResult());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fieldAchieved(DependencyChecker dependencyChecker, FieldDependency field) {
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ 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.MethodReference;
|
||||
import org.teavm.model.*;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -41,6 +41,12 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
case "getSuperclass":
|
||||
generateGetSuperclass(context, writer);
|
||||
break;
|
||||
case "forNameImpl":
|
||||
generateForName(context, writer);
|
||||
break;
|
||||
case "newInstance":
|
||||
generateNewInstance(context, writer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,6 +108,43 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
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("<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 === null) {").indent().softNewLine();
|
||||
writer.append("var ex = new ").appendClass(InstantiationException.class.getName()).append("();");
|
||||
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)");
|
||||
writer.append("return instance");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void methodAchieved(DependencyChecker checker, MethodDependency graph) {
|
||||
switch (graph.getReference().getName()) {
|
||||
|
@ -110,6 +153,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
|
|||
case "wrap":
|
||||
case "getSuperclass":
|
||||
case "getComponentType0":
|
||||
case "forNameImpl":
|
||||
graph.getResult().propagate("java.lang.Class");
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -109,4 +109,29 @@ public class TClass<T extends TObject> extends TObject {
|
|||
}
|
||||
return (T)obj;
|
||||
}
|
||||
|
||||
public TClassLoader getClassLoader() {
|
||||
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) {
|
||||
throw new TClassNotFoundException();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static TClass<?> forName(TString name, boolean initialize, TClassLoader loader)
|
||||
throws TClassNotFoundException {
|
||||
return forName(name);
|
||||
}
|
||||
|
||||
@GeneratedBy(ClassNativeGenerator.class)
|
||||
public native T newInstance() throws TInstantiationException, TIllegalAccessException;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public abstract class TClassLoader extends TObject {
|
||||
private TClassLoader parent;
|
||||
private static TSystemClassLoader systemClassLoader = new TSystemClassLoader();
|
||||
|
||||
protected TClassLoader() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
protected TClassLoader(TClassLoader parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public TClassLoader getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public static TClassLoader getSystemClassLoader() {
|
||||
return systemClassLoader;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class TClassNotFoundException extends TReflectiveOperationException {
|
||||
private static final long serialVersionUID = -1162632869775788325L;
|
||||
|
||||
public TClassNotFoundException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TClassNotFoundException(TString message, TThrowable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TClassNotFoundException(TString message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class TIllegalAccessException extends ReflectiveOperationException {
|
||||
private static final long serialVersionUID = 8240407889170934565L;
|
||||
|
||||
public TIllegalAccessException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TIllegalAccessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class TInstantiationException extends ReflectiveOperationException {
|
||||
private static final long serialVersionUID = 8771605296206833516L;
|
||||
|
||||
public TInstantiationException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TInstantiationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class TReflectiveOperationException extends TException {
|
||||
private static final long serialVersionUID = -455785869284249992L;
|
||||
|
||||
public TReflectiveOperationException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TReflectiveOperationException(TString message, TThrowable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TReflectiveOperationException(TString message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TReflectiveOperationException(TThrowable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
class TSystemClassLoader extends TClassLoader {
|
||||
TSystemClassLoader() {
|
||||
}
|
||||
}
|
|
@ -29,8 +29,8 @@ public class LoggerNativeGenerator implements Generator {
|
|||
@Override
|
||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||
writer.append("if (console) {").indent().softNewLine();
|
||||
writer.append("console.").append(methodRef.getName()).append("(").append(context.getParameterName(1))
|
||||
.append(");").softNewLine();
|
||||
writer.append("console.").append(methodRef.getName()).append("($rt_ustr(").append(context.getParameterName(1))
|
||||
.append("));").softNewLine();
|
||||
writer.outdent().append("}").softNewLine();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,4 +89,12 @@ public class ClassTest {
|
|||
Object obj = 23;
|
||||
Float.class.cast(obj);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void instanceCreatedThroughReflection() throws Exception {
|
||||
Runnable instance = (Runnable)Class.forName(TestObject.class.getName()).newInstance();
|
||||
instance.run();
|
||||
assertEquals(TestObject.class, instance.getClass());
|
||||
assertEquals(1, ((TestObject)instance).getCounter());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public class TestObject extends Object implements Runnable {
|
||||
private int counter;
|
||||
|
||||
public TestObject() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
++counter;
|
||||
}
|
||||
|
||||
public int getCounter() {
|
||||
return counter;
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
private static final String variableNames = "abcdefghijkmnopqrstuvwxyz";
|
||||
private NamingStrategy naming;
|
||||
private SourceWriter writer;
|
||||
private ClassHolderSource classSource;
|
||||
private ListableClassHolderSource classSource;
|
||||
private ClassLoader classLoader;
|
||||
private boolean minifying;
|
||||
private Map<MethodReference, InjectorHolder> injectorMap = new HashMap<>();
|
||||
|
@ -50,7 +50,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
public Renderer(SourceWriter writer, ClassHolderSource classSource, ClassLoader classLoader) {
|
||||
public Renderer(SourceWriter writer, ListableClassHolderSource classSource, ClassLoader classLoader) {
|
||||
this.naming = writer.getNaming();
|
||||
this.writer = writer;
|
||||
this.classSource = classSource;
|
||||
|
@ -442,7 +442,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ClassReaderSource getClassSource() {
|
||||
public ListableClassReaderSource getClassSource() {
|
||||
return classSource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
package org.teavm.javascript.ni;
|
||||
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -24,5 +24,5 @@ import org.teavm.model.ClassReaderSource;
|
|||
public interface GeneratorContext {
|
||||
String getParameterName(int index);
|
||||
|
||||
ClassReaderSource getClassSource();
|
||||
ListableClassReaderSource getClassSource();
|
||||
}
|
||||
|
|
|
@ -15,12 +15,9 @@
|
|||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface ListableClassHolderSource extends ClassHolderSource {
|
||||
Set<String> getClassNames();
|
||||
public interface ListableClassHolderSource extends ClassHolderSource, ListableClassReaderSource {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.model;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||
*/
|
||||
public interface ListableClassReaderSource extends ClassReaderSource {
|
||||
Set<String> getClassNames();
|
||||
}
|
Loading…
Reference in New Issue
Block a user