mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds possibility to implement JSObject ant pass it as a callback to a
method of another JSObject
This commit is contained in:
parent
c9f78c5cdf
commit
48265c446f
|
@ -144,7 +144,7 @@ class DependencyGraphBuilder {
|
||||||
if (insn.getInstance() != null) {
|
if (insn.getInstance() != null) {
|
||||||
nodes[insn.getInstance().getIndex()].connect(targetParams[0]);
|
nodes[insn.getInstance().getIndex()].connect(targetParams[0]);
|
||||||
}
|
}
|
||||||
if (targetGraph.getResultNode() != null) {
|
if (targetGraph.getResultNode() != null && insn.getReceiver() != null) {
|
||||||
targetGraph.getResultNode().connect(nodes[insn.getReceiver().getIndex()]);
|
targetGraph.getResultNode().connect(nodes[insn.getReceiver().getIndex()]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import org.teavm.javascript.ast.*;
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
import org.teavm.javascript.ni.GeneratedBy;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.InjectedBy;
|
import org.teavm.javascript.ni.InjectedBy;
|
||||||
|
import org.teavm.javascript.ni.PreserveOriginalName;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
import org.teavm.model.util.ProgramUtils;
|
import org.teavm.model.util.ProgramUtils;
|
||||||
|
|
||||||
|
@ -121,7 +122,11 @@ public class Decompiler {
|
||||||
if (method.getAnnotations().get(InjectedBy.class.getName()) != null) {
|
if (method.getAnnotations().get(InjectedBy.class.getName()) != null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
clsNode.getMethods().add(decompile(method));
|
MethodNode methodNode = decompile(method);
|
||||||
|
clsNode.getMethods().add(methodNode);
|
||||||
|
if (method.getAnnotations().get(PreserveOriginalName.class.getName()) != null) {
|
||||||
|
methodNode.setOriginalNamePreserved(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
clsNode.getInterfaces().addAll(cls.getInterfaces());
|
clsNode.getInterfaces().addAll(cls.getInterfaces());
|
||||||
clsNode.getModifiers().addAll(mapModifiers(cls.getModifiers()));
|
clsNode.getModifiers().addAll(mapModifiers(cls.getModifiers()));
|
||||||
|
|
|
@ -26,13 +26,38 @@ import org.teavm.model.instructions.*;
|
||||||
*/
|
*/
|
||||||
class JavascriptNativeProcessor {
|
class JavascriptNativeProcessor {
|
||||||
private ClassHolderSource classSource;
|
private ClassHolderSource classSource;
|
||||||
private Map<String, Boolean> knownJavaScriptClasses = new HashMap<>();
|
|
||||||
private Program program;
|
private Program program;
|
||||||
private List<Instruction> replacement = new ArrayList<>();
|
private List<Instruction> replacement = new ArrayList<>();
|
||||||
|
private NativeJavascriptClassRepository nativeRepos;
|
||||||
|
|
||||||
public JavascriptNativeProcessor(ClassHolderSource classSource) {
|
public JavascriptNativeProcessor(ClassHolderSource classSource) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
knownJavaScriptClasses.put(JSObject.class.getName(), true);
|
nativeRepos = new NativeJavascriptClassRepository(classSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processClass(ClassHolder cls) {
|
||||||
|
Set<MethodDescriptor> preservedMethods = new HashSet<>();
|
||||||
|
for (String iface : cls.getInterfaces()) {
|
||||||
|
if (nativeRepos.isJavaScriptClass(iface)) {
|
||||||
|
addPreservedMethods(iface, preservedMethods);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
if (preservedMethods.contains(method.getDescriptor()) &&
|
||||||
|
method.getAnnotations().get(PreserveOriginalName.class.getName()) == null) {
|
||||||
|
method.getAnnotations().add(new AnnotationHolder(PreserveOriginalName.class.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPreservedMethods(String ifaceName, Set<MethodDescriptor> methods) {
|
||||||
|
ClassHolder iface = classSource.getClassHolder(ifaceName);
|
||||||
|
for (MethodHolder method : iface.getMethods()) {
|
||||||
|
methods.add(method.getDescriptor());
|
||||||
|
}
|
||||||
|
for (String superIfaceName : iface.getInterfaces()) {
|
||||||
|
addPreservedMethods(superIfaceName, methods);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void processProgram(Program program) {
|
public void processProgram(Program program) {
|
||||||
|
@ -46,7 +71,7 @@ class JavascriptNativeProcessor {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
InvokeInstruction invoke = (InvokeInstruction)insn;
|
InvokeInstruction invoke = (InvokeInstruction)insn;
|
||||||
if (!isJavaScriptClass(invoke.getMethod().getClassName())) {
|
if (!nativeRepos.isJavaScriptClass(invoke.getMethod().getClassName())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
replacement.clear();
|
replacement.clear();
|
||||||
|
@ -86,7 +111,7 @@ class JavascriptNativeProcessor {
|
||||||
"a proper native JavaScript indexer declaration");
|
"a proper native JavaScript indexer declaration");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!isSupportedType(method.getResultType())) {
|
if (method.getResultType() != ValueType.VOID && !isSupportedType(method.getResultType())) {
|
||||||
throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
|
throw new RuntimeException("Method " + invoke.getMethod() + " is not " +
|
||||||
"a proper native JavaScript method declaration");
|
"a proper native JavaScript method declaration");
|
||||||
}
|
}
|
||||||
|
@ -258,28 +283,6 @@ class JavascriptNativeProcessor {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isJavaScriptClass(String className) {
|
|
||||||
Boolean known = knownJavaScriptClasses.get(className);
|
|
||||||
if (known == null) {
|
|
||||||
known = exploreIfJavaScriptClass(className);
|
|
||||||
knownJavaScriptClasses.put(className, known);
|
|
||||||
}
|
|
||||||
return known;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean exploreIfJavaScriptClass(String className) {
|
|
||||||
ClassHolder cls = classSource.getClassHolder(className);
|
|
||||||
if (cls == null || !cls.getModifiers().contains(ElementModifier.INTERFACE)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (String iface : cls.getInterfaces()) {
|
|
||||||
if (isJavaScriptClass(iface)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MethodHolder getMethod(MethodReference ref) {
|
private MethodHolder getMethod(MethodReference ref) {
|
||||||
ClassHolder cls = classSource.getClassHolder(ref.getClassName());
|
ClassHolder cls = classSource.getClassHolder(ref.getClassName());
|
||||||
MethodHolder method = cls.getMethod(ref.getDescriptor());
|
MethodHolder method = cls.getMethod(ref.getDescriptor());
|
||||||
|
@ -359,7 +362,7 @@ class JavascriptNativeProcessor {
|
||||||
return isSupportedType(((ValueType.Array)type).getItemType());
|
return isSupportedType(((ValueType.Array)type).getItemType());
|
||||||
} else if (type instanceof ValueType.Object) {
|
} else if (type instanceof ValueType.Object) {
|
||||||
String typeName = ((ValueType.Object)type).getClassName();
|
String typeName = ((ValueType.Object)type).getClassName();
|
||||||
return typeName.equals("java.lang.String") || isJavaScriptClass(typeName);
|
return typeName.equals("java.lang.String") || nativeRepos.isJavaScriptClass(typeName);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.teavm.model.MethodHolder;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class JavascriptProcessedClassSource implements ClassHolderSource {
|
public class JavascriptProcessedClassSource implements ClassHolderSource {
|
||||||
|
private ThreadLocal<JavascriptNativeProcessor> processor = new ThreadLocal<>();
|
||||||
private ClassHolderSource innerSource;
|
private ClassHolderSource innerSource;
|
||||||
|
|
||||||
public JavascriptProcessedClassSource(ClassHolderSource innerSource) {
|
public JavascriptProcessedClassSource(ClassHolderSource innerSource) {
|
||||||
|
@ -40,11 +41,19 @@ public class JavascriptProcessedClassSource implements ClassHolderSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void transformClass(ClassHolder cls) {
|
private void transformClass(ClassHolder cls) {
|
||||||
JavascriptNativeProcessor processor = new JavascriptNativeProcessor(innerSource);
|
JavascriptNativeProcessor processor = getProcessor();
|
||||||
|
processor.processClass(cls);
|
||||||
for (MethodHolder method : cls.getMethods()) {
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
if (method.getProgram() != null) {
|
if (method.getProgram() != null) {
|
||||||
processor.processProgram(method.getProgram());
|
processor.processProgram(method.getProgram());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JavascriptNativeProcessor getProcessor() {
|
||||||
|
if (processor.get() == null) {
|
||||||
|
processor.set(new JavascriptNativeProcessor(innerSource));
|
||||||
|
}
|
||||||
|
return processor.get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.teavm.javascript;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.javascript.ni.JSObject;
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
|
import org.teavm.model.ClassHolderSource;
|
||||||
|
import org.teavm.model.ElementModifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class NativeJavascriptClassRepository {
|
||||||
|
private ClassHolderSource classSource;
|
||||||
|
private Map<String, Boolean> knownJavaScriptClasses = new HashMap<>();
|
||||||
|
|
||||||
|
public NativeJavascriptClassRepository(ClassHolderSource classSource) {
|
||||||
|
this.classSource = classSource;
|
||||||
|
knownJavaScriptClasses.put(JSObject.class.getName(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isJavaScriptClass(String className) {
|
||||||
|
Boolean known = knownJavaScriptClasses.get(className);
|
||||||
|
if (known == null) {
|
||||||
|
known = figureOutIfJavaScriptClass(className);
|
||||||
|
knownJavaScriptClasses.put(className, known);
|
||||||
|
}
|
||||||
|
return known;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean figureOutIfJavaScriptClass(String className) {
|
||||||
|
ClassHolder cls = classSource.getClassHolder(className);
|
||||||
|
if (cls == null || !cls.getModifiers().contains(ElementModifier.INTERFACE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (String iface : cls.getInterfaces()) {
|
||||||
|
if (isJavaScriptClass(iface)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -290,15 +290,8 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
if (ref.getDescriptor().getName().equals("<init>")) {
|
if (ref.getDescriptor().getName().equals("<init>")) {
|
||||||
renderInitializer(method);
|
renderInitializer(method);
|
||||||
}
|
}
|
||||||
int startParam = 0;
|
writer.appendClass(ref.getClassName()).append(".prototype.").appendMethod(ref)
|
||||||
if (method.getModifiers().contains(NodeModifier.STATIC)) {
|
.ws().append("=").ws().append("function(");
|
||||||
startParam = 1;
|
|
||||||
}
|
|
||||||
writer.appendClass(ref.getClassName()).append('.');
|
|
||||||
if (startParam == 0) {
|
|
||||||
writer.append("prototype.");
|
|
||||||
}
|
|
||||||
writer.appendMethod(ref).ws().append("=").ws().append("function(");
|
|
||||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||||
if (i > 1) {
|
if (i > 1) {
|
||||||
writer.append(", ");
|
writer.append(", ");
|
||||||
|
@ -307,17 +300,17 @@ public class Renderer implements ExprVisitor, StatementVisitor {
|
||||||
}
|
}
|
||||||
writer.append(")").ws().append("{").softNewLine().indent();
|
writer.append(")").ws().append("{").softNewLine().indent();
|
||||||
writer.append("return ").appendMethodBody(ref).append("(");
|
writer.append("return ").appendMethodBody(ref).append("(");
|
||||||
if (startParam == 0) {
|
writer.append("this");
|
||||||
writer.append("this");
|
|
||||||
}
|
|
||||||
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
for (int i = 1; i <= ref.parameterCount(); ++i) {
|
||||||
if (i > 1 || startParam == 0) {
|
writer.append(",").ws().append(variableName(i));
|
||||||
writer.append(",").ws();
|
|
||||||
}
|
|
||||||
writer.append(variableName(i));
|
|
||||||
}
|
}
|
||||||
writer.append(");").softNewLine();
|
writer.append(");").softNewLine();
|
||||||
writer.outdent().append("}").newLine();
|
writer.outdent().append("}").newLine();
|
||||||
|
if (method.isOriginalNamePreserved()) {
|
||||||
|
writer.appendClass(ref.getClassName()).append(".prototype.").append(ref.getName()).ws().append("=")
|
||||||
|
.ws().appendClass(ref.getClassName()).append(".prototype.").appendMethod(ref)
|
||||||
|
.append(';').newLine();
|
||||||
|
}
|
||||||
} catch (NamingException e) {
|
} catch (NamingException e) {
|
||||||
throw new RenderingException("Error rendering method " + method.getReference() + ". " +
|
throw new RenderingException("Error rendering method " + method.getReference() + ". " +
|
||||||
"See cause for details", e);
|
"See cause for details", e);
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.teavm.model.MethodReference;
|
||||||
public abstract class MethodNode {
|
public abstract class MethodNode {
|
||||||
private MethodReference reference;
|
private MethodReference reference;
|
||||||
private Set<NodeModifier> modifiers = EnumSet.noneOf(NodeModifier.class);
|
private Set<NodeModifier> modifiers = EnumSet.noneOf(NodeModifier.class);
|
||||||
|
private boolean originalNamePreserved;
|
||||||
|
|
||||||
public MethodNode(MethodReference reference) {
|
public MethodNode(MethodReference reference) {
|
||||||
this.reference = reference;
|
this.reference = reference;
|
||||||
|
@ -40,5 +41,13 @@ public abstract class MethodNode {
|
||||||
return modifiers;
|
return modifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOriginalNamePreserved() {
|
||||||
|
return originalNamePreserved;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOriginalNamePreserved(boolean originalNamePreserved) {
|
||||||
|
this.originalNamePreserved = originalNamePreserved;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract void acceptVisitor(MethodNodeVisitor visitor);
|
public abstract void acceptVisitor(MethodNodeVisitor visitor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package org.teavm.javascript.ni;
|
package org.teavm.javascript.ni;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import org.teavm.dependency.PluggableDependency;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -66,6 +67,9 @@ public final class JS {
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
public static native JSObject wrap(double num);
|
public static native JSObject wrap(double num);
|
||||||
|
|
||||||
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
public static native JSObject wrap(boolean num);
|
||||||
|
|
||||||
public static <T extends JSObject> JSArray<T> wrap(T[] array) {
|
public static <T extends JSObject> JSArray<T> wrap(T[] array) {
|
||||||
JSArray<T> result = createArray(array.length);
|
JSArray<T> result = createArray(array.length);
|
||||||
for (int i = 0; i < array.length; ++i) {
|
for (int i = 0; i < array.length; ++i) {
|
||||||
|
@ -120,34 +124,43 @@ public final class JS {
|
||||||
public static native boolean isUndefined(JSObject obj);
|
public static native boolean isUndefined(JSObject obj);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method);
|
public static native JSObject invoke(JSObject instance, JSObject method);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a);
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b);
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c);
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d);
|
JSObject d);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d, JSObject e);
|
JSObject d, JSObject e);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d, JSObject e, JSObject f);
|
JSObject d, JSObject e, JSObject f);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d, JSObject e, JSObject f, JSObject g);
|
JSObject d, JSObject e, JSObject f, JSObject g);
|
||||||
|
|
||||||
@InjectedBy(JSNativeGenerator.class)
|
@InjectedBy(JSNativeGenerator.class)
|
||||||
|
@PluggableDependency(JSNativeGenerator.class)
|
||||||
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
public static native JSObject invoke(JSObject instance, JSObject method, JSObject a, JSObject b, JSObject c,
|
||||||
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h);
|
JSObject d, JSObject e, JSObject f, JSObject g, JSObject h);
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,23 @@ package org.teavm.javascript.ni;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
|
import org.teavm.dependency.DependencyChecker;
|
||||||
|
import org.teavm.dependency.DependencyConsumer;
|
||||||
|
import org.teavm.dependency.DependencyPlugin;
|
||||||
|
import org.teavm.dependency.MethodGraph;
|
||||||
import org.teavm.javascript.ast.ConstantExpr;
|
import org.teavm.javascript.ast.ConstantExpr;
|
||||||
import org.teavm.javascript.ast.Expr;
|
import org.teavm.javascript.ast.Expr;
|
||||||
import org.teavm.javascript.ast.InvocationExpr;
|
import org.teavm.javascript.ast.InvocationExpr;
|
||||||
|
import org.teavm.model.ClassHolder;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
|
import org.teavm.model.MethodHolder;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class JSNativeGenerator implements Generator, Injector {
|
public class JSNativeGenerator implements Generator, Injector, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
|
@ -87,6 +93,27 @@ public class JSNativeGenerator implements Generator, Injector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void methodAchieved(final DependencyChecker checker, MethodReference method) {
|
||||||
|
MethodGraph graph = checker.attachMethodGraph(method);
|
||||||
|
for (int i = 0; i < method.parameterCount(); ++i) {
|
||||||
|
graph.getVariableNode(i).addConsumer(new DependencyConsumer() {
|
||||||
|
@Override public void consume(String type) {
|
||||||
|
achieveFunctorMethods(checker, type);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void achieveFunctorMethods(DependencyChecker checker, String type) {
|
||||||
|
ClassHolder cls = checker.getClassSource().getClassHolder(type);
|
||||||
|
if (cls != null) {
|
||||||
|
for (MethodHolder method : cls.getMethods()) {
|
||||||
|
checker.attachMethodGraph(method.getReference());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void generateWrapString(GeneratorContext context, SourceWriter writer) throws IOException {
|
private void generateWrapString(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
FieldReference charsField = new FieldReference("java.lang.String", "characters");
|
FieldReference charsField = new FieldReference("java.lang.String", "characters");
|
||||||
writer.append("var result = \"\";").softNewLine();
|
writer.append("var result = \"\";").softNewLine();
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.teavm.javascript.ni;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface PreserveOriginalName {
|
||||||
|
}
|
|
@ -39,6 +39,9 @@ public class Parser {
|
||||||
ssaProducer.transformToSSA(program, method.getParameterTypes());
|
ssaProducer.transformToSSA(program, method.getParameterTypes());
|
||||||
method.setProgram(program);
|
method.setProgram(program);
|
||||||
parseAnnotations(method.getAnnotations(), node);
|
parseAnnotations(method.getAnnotations(), node);
|
||||||
|
while (program.variableCount() <= method.parameterCount()) {
|
||||||
|
program.createVariable();
|
||||||
|
}
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,9 @@ public class SSATransformer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applySignature() {
|
private void applySignature() {
|
||||||
|
if (program.variableCount() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int index = 0;
|
int index = 0;
|
||||||
variableMap[index] = program.variableAt(index);
|
variableMap[index] = program.variableAt(index);
|
||||||
++index;
|
++index;
|
||||||
|
|
|
@ -16,12 +16,13 @@
|
||||||
package org.teavm.dom.events;
|
package org.teavm.dom.events;
|
||||||
|
|
||||||
import org.teavm.javascript.ni.JSFunctor;
|
import org.teavm.javascript.ni.JSFunctor;
|
||||||
|
import org.teavm.javascript.ni.JSObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
@JSFunctor
|
@JSFunctor
|
||||||
public interface EventListener {
|
public interface EventListener extends JSObject {
|
||||||
void handleEvent(Event evt);
|
void handleEvent(Event evt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ package org.teavm.samples;
|
||||||
import org.teavm.dom.core.Document;
|
import org.teavm.dom.core.Document;
|
||||||
import org.teavm.dom.core.Element;
|
import org.teavm.dom.core.Element;
|
||||||
import org.teavm.dom.core.Window;
|
import org.teavm.dom.core.Window;
|
||||||
|
import org.teavm.dom.events.Event;
|
||||||
|
import org.teavm.dom.events.EventListener;
|
||||||
|
import org.teavm.dom.events.EventTarget;
|
||||||
import org.teavm.javascript.ni.JS;
|
import org.teavm.javascript.ni.JS;
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +37,24 @@ public class HelloWorld {
|
||||||
window = (Window)JS.getGlobal();
|
window = (Window)JS.getGlobal();
|
||||||
document = window.getDocument();
|
document = window.getDocument();
|
||||||
body = document.getDocumentElement().getElementsByTagName("body").item(0);
|
body = document.getDocumentElement().getElementsByTagName("body").item(0);
|
||||||
|
createButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createButton() {
|
||||||
|
Element elem = document.createElement("div");
|
||||||
|
body.appendChild(elem);
|
||||||
|
final Element button = document.createElement("button");
|
||||||
|
button.appendChild(document.createTextNode("Click me!"));
|
||||||
|
elem.appendChild(button);
|
||||||
|
((EventTarget)button).addEventListener("click", new EventListener() {
|
||||||
|
@Override public void handleEvent(Event evt) {
|
||||||
|
button.getParentNode().removeChild(button);
|
||||||
|
printHelloWorld();
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void printHelloWorld() {
|
||||||
println("Hello, world!");
|
println("Hello, world!");
|
||||||
println("Here is the Fibonacci sequence:");
|
println("Here is the Fibonacci sequence:");
|
||||||
long a = 0;
|
long a = 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user