diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/impl/report/JCLComparisonVisitor.java b/teavm-classlib/src/main/java/org/teavm/classlib/impl/report/JCLComparisonVisitor.java index c82b298b0..3e8ebf29b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/impl/report/JCLComparisonVisitor.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/impl/report/JCLComparisonVisitor.java @@ -32,7 +32,7 @@ class JCLComparisonVisitor extends ClassVisitor { private JCLClass jclClass; public JCLComparisonVisitor(ClassReaderSource classSource, Map packageMap) { - super(Opcodes.ASM4); + super(Opcodes.ASM5); this.classSource = classSource; this.packageMap = packageMap; } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java index 016b67253..b64d4305b 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TMath.java @@ -93,7 +93,7 @@ public final class TMath extends TObject { public static native double atan2(double y, double x); public static int round(float a) { - return (int)(a + 1.5f); + return (int)(a + 0.5f); } public static long round(double a) { diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TStackTraceElement.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TStackTraceElement.java new file mode 100644 index 000000000..2ae62814a --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TStackTraceElement.java @@ -0,0 +1,94 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.classlib.java.lang; + +import java.util.Objects; +import org.teavm.classlib.java.io.TSerializable; +import org.teavm.classlib.java.util.TObjects; + +/** + * + * @author Alexey Andreev + */ +public final class TStackTraceElement extends TObject implements TSerializable { + private TString declaringClass; + private TString methodName; + private TString fileName; + private int lineNumber; + + public TStackTraceElement(TString declaringClass, TString methodName, TString fileName, int lineNumber) { + if (declaringClass == null || methodName == null) { + throw new TNullPointerException(); + } + this.declaringClass = declaringClass; + this.methodName = methodName; + this.fileName = fileName; + this.lineNumber = lineNumber; + } + + public TString getClassName() { + return declaringClass; + } + + public TString getMethodName() { + return methodName; + } + + public TString getFileName() { + return fileName; + } + + public int getLineNumber() { + return lineNumber; + } + + public boolean isNativeMethod() { + return fileName == null; + } + + @Override + public int hashCode() { + return Objects.hash(declaringClass, methodName, fileName, lineNumber); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof TStackTraceElement)) { + return false; + } + TStackTraceElement other = (TStackTraceElement)obj; + return TObjects.equals(declaringClass, other.declaringClass) && + TObjects.equals(methodName, other.methodName) && + TObjects.equals(fileName, other.fileName) && + lineNumber == other.lineNumber; + } + + @Override + public String toString() { + TStringBuilder sb = new TStringBuilder(); + int index = declaringClass.lastIndexOf('.'); + sb.append(declaringClass.substring(index + 1)).append('.').append(methodName).append('('); + if (fileName != null) { + sb.append(fileName).append(':').append(lineNumber); + } else { + sb.append(TString.wrap("Unknown Source")); + } + return sb.toString(); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java index 4b98842c1..c4de1d645 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java @@ -167,4 +167,8 @@ public class TThread extends TObject implements TRunnable { public final int getPriority(){ return this.priority; } + + public TStackTraceElement[] getStackTrace() { + return new TStackTraceElement[0]; + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java index 6471e8440..70ab398d6 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java @@ -146,6 +146,15 @@ public class TThrowable extends RuntimeException { stream.println(TString.wrap(getClass().getName() + ": " + getMessage())); } + @Rename("getStackTrace") + public TStackTraceElement[] getStackTrace0() { + return new TStackTraceElement[0]; + } + + public void setStackTrace(@SuppressWarnings("unused") TStackTraceElement[] stackTrace) { + // do nothing + } + @Rename("getSuppressed") public final TThrowable[] getSuppressed0() { return TArrays.copyOf(suppressed, suppressed.length); diff --git a/teavm-core/src/main/java/org/teavm/common/GraphIndexer.java b/teavm-core/src/main/java/org/teavm/common/GraphIndexer.java index 21f1b94c6..f1b2707c2 100644 --- a/teavm-core/src/main/java/org/teavm/common/GraphIndexer.java +++ b/teavm-core/src/main/java/org/teavm/common/GraphIndexer.java @@ -37,11 +37,14 @@ public class GraphIndexer { private DominatorTree domTree; private int lastIndex; private int[] weights; + private int[] priorities; - public GraphIndexer(Graph graph, int[] weights) { + public GraphIndexer(Graph graph, int[] weights, int[] priorities) { int sz = graph.size(); - this.weights = weights; - propagateWeights(graph, weights); + this.weights = weights.clone(); + propagateWeights(graph, this.weights); + this.priorities = priorities.clone(); + propagatePriorities(graph, this.priorities); indexToNode = new int[sz + 1]; nodeToIndex = new int[sz + 1]; Arrays.fill(nodeToIndex, -1); @@ -99,6 +102,39 @@ public class GraphIndexer { } } + private void propagatePriorities(Graph graph, int[] priorities) { + boolean allZero = true; + for (int i = 0; i < priorities.length; ++i) { + if (priorities[i] != 0) { + allZero = false; + break; + } + } + if (allZero) { + return; + } + + DominatorTree domTree = GraphUtils.buildDominatorTree(graph); + Graph domGraph = GraphUtils.buildDominatorGraph(domTree, graph.size()); + IntegerStack stack = new IntegerStack(graph.size() * 2); + for (int i = 0; i < domGraph.size(); ++i) { + if (domGraph.outgoingEdgesCount(i) == 0) { + stack.push(i); + } + } + while (!stack.isEmpty()) { + int node = stack.pop(); + int parent = domTree.immediateDominatorOf(node); + if (parent < 0) { + continue; + } + if (priorities[parent] < priorities[node]) { + priorities[parent] = priorities[node]; + stack.push(parent); + } + } + } + private void sort(Graph graph) { int sz = graph.size(); byte[] state = new byte[sz]; @@ -128,7 +164,7 @@ public class GraphIndexer { IntSet loopNodes = IntOpenHashSet.from(findNaturalLoop(node, terminalNodes.getAll())); for (int succ : successors) { if (loopNodes.contains(succ)) { - succList.add(new WeightedNode(succ, weights[succ])); + succList.add(new WeightedNode(succ, priorities[succ], weights[succ])); } } Collections.sort(succList); @@ -142,7 +178,7 @@ public class GraphIndexer { for (int succ : graph.outgoingEdges(loopNode.value)) { if (!loopNodes.contains(succ)) { if (outerSuccessors.add(succ)) { - succList.add(new WeightedNode(succ, weights[succ])); + succList.add(new WeightedNode(succ, priorities[succ], weights[succ])); } } } @@ -153,7 +189,7 @@ public class GraphIndexer { } } else { for (int succ : successors) { - succList.add(new WeightedNode(succ, weights[succ])); + succList.add(new WeightedNode(succ, priorities[succ], weights[succ])); } Collections.sort(succList); for (WeightedNode wnode : succList) { @@ -209,15 +245,21 @@ public class GraphIndexer { static class WeightedNode implements Comparable { int index; + int priority; int weight; - public WeightedNode(int index, int weight) { + public WeightedNode(int index, int priority, int weight) { this.index = index; + this.priority = priority; this.weight = weight; } @Override public int compareTo(WeightedNode o) { + int r = Integer.compare(priority, o.priority); + if (r != 0) { + return r; + } return Integer.compare(weight, o.weight); } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/BreakEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/BreakEliminator.java index bff4928d8..db0420473 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/BreakEliminator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/BreakEliminator.java @@ -156,6 +156,6 @@ class BreakEliminator implements StatementVisitor { } private boolean escapes(List statements) { - return new EscapingStatementFinder().check(statements); + return new EscapingStatementFinder(usageCounter).check(statements); } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java index 97e19d484..ca3ba41be 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java @@ -338,7 +338,13 @@ public class Decompiler { for (int i = 0; i < weights.length; ++i) { weights[i] = program.basicBlockAt(i).getInstructions().size(); } - indexer = new GraphIndexer(graph, weights); + int[] priorities = new int[graph.size()]; + for (int i = 0; i < targetBlocks.length; ++i) { + if (targetBlocks[i] >= 0) { + priorities[i] = 1; + } + } + indexer = new GraphIndexer(graph, weights, priorities); graph = indexer.getGraph(); loopGraph = new LoopGraph(this.graph); unflatCode(); diff --git a/teavm-core/src/main/java/org/teavm/javascript/EscapingStatementFinder.java b/teavm-core/src/main/java/org/teavm/javascript/EscapingStatementFinder.java index 921ac1142..6ee00fe5e 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/EscapingStatementFinder.java +++ b/teavm-core/src/main/java/org/teavm/javascript/EscapingStatementFinder.java @@ -15,9 +15,7 @@ */ package org.teavm.javascript; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.teavm.javascript.ast.*; /** @@ -25,39 +23,48 @@ import org.teavm.javascript.ast.*; * @author Alexey Andreev */ class EscapingStatementFinder implements StatementVisitor { + AllBlocksCountVisitor blockCountVisitor; public boolean escaping; - private boolean last = true; - private Set outerStatements = new HashSet<>(); - private Set breakTargets = new HashSet<>(); - private IdentifiedStatement currentBlock; + + public EscapingStatementFinder(AllBlocksCountVisitor blockCountVisitor) { + this.blockCountVisitor = blockCountVisitor; + } + + private boolean isEmpty(Statement statement) { + if (!(statement instanceof SequentialStatement)) { + return false; + } + SequentialStatement seq = (SequentialStatement)statement; + for (int i = seq.getSequence().size() - 1; i >= 0; --i) { + if (!isEmpty(seq.getSequence().get(i))) { + return false; + } + } + return true; + } public boolean check(List statements) { if (escaping) { return true; } if (statements.isEmpty()) { - escaping = last; + escaping = true; return true; } - boolean oldLast = last; - for (int i = 0; i < statements.size(); ++i) { - last = false; - statements.get(i).acceptVisitor(this); - if (escaping) { - break; + for (int i = statements.size() - 1; i >= 0; --i) { + Statement stmt = statements.get(i); + if (!isEmpty(stmt)) { + stmt.acceptVisitor(this); + return escaping; } } - last = oldLast; - if (!escaping) { - statements.get(statements.size() - 1).acceptVisitor(this); - } - last = oldLast; - return escaping; + escaping = true; + return true; } @Override public void visit(AssignmentStatement statement) { - escaping |= last; + escaping |= true; } @Override @@ -74,56 +81,42 @@ class EscapingStatementFinder implements StatementVisitor { @Override public void visit(SwitchStatement statement) { - IdentifiedStatement oldCurrentBlock = currentBlock; - currentBlock = statement; - outerStatements.add(statement); + if (blockCountVisitor.getCount(statement) > 0) { + escaping = true; + return; + } for (SwitchClause clause : statement.getClauses()) { if (check(clause.getBody())) { break; } } - check(statement.getDefaultClause()); - outerStatements.remove(statement); - currentBlock = oldCurrentBlock; - if (breakTargets.contains(statement)) { - escaping |= last; + if (!escaping) { + check(statement.getDefaultClause()); } } @Override public void visit(WhileStatement statement) { - IdentifiedStatement oldCurrentBlock = currentBlock; - currentBlock = statement; - outerStatements.add(statement); - if (!check(statement.getBody()) && statement.getCondition() != null) { - escaping |= last; + if (blockCountVisitor.getCount(statement) > 0) { + escaping = true; + return; } - outerStatements.remove(statement); - currentBlock = oldCurrentBlock; - if (breakTargets.contains(statement)) { - escaping |= last; + if (statement.getCondition() != null && check(statement.getBody())) { + escaping = true; } } @Override public void visit(BlockStatement statement) { - IdentifiedStatement oldCurrentBlock = currentBlock; - currentBlock = statement; - outerStatements.add(statement); - check(statement.getBody()); - outerStatements.remove(statement); - currentBlock = oldCurrentBlock; - if (breakTargets.contains(statement)) { - escaping |= last; + if (blockCountVisitor.getCount(statement) > 0) { + escaping = true; + return; } + check(statement.getBody()); } @Override public void visit(BreakStatement statement) { - IdentifiedStatement target = statement.getTarget() != null ? statement.getTarget() : currentBlock; - if (target != null) { - breakTargets.add(target); - } } @Override @@ -140,13 +133,14 @@ class EscapingStatementFinder implements StatementVisitor { @Override public void visit(InitClassStatement statement) { - escaping |= last; + escaping = true; } @Override public void visit(TryCatchStatement statement) { - check(statement.getProtectedBody()); - check(statement.getHandler()); + if (!check(statement.getProtectedBody())) { + check(statement.getHandler()); + } } @Override @@ -155,11 +149,11 @@ class EscapingStatementFinder implements StatementVisitor { @Override public void visit(MonitorEnterStatement statement) { - escaping |= last; + escaping = true; } @Override public void visit(MonitorExitStatement statement) { - escaping |= last; + escaping = true; } } 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 cd89dc1d6..3451cd4c8 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -67,6 +67,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext private Map blockIdMap = new HashMap<>(); private List> debugNames = new ArrayList<>(); private List cachedVariableNames = new ArrayList<>(); + private boolean end; + private int currentPart; private static class OperatorPrecedence { Priority priority; @@ -657,6 +659,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } writer.append(";").softNewLine(); } + end = true; + currentPart = 0; method.getBody().acceptVisitor(Renderer.this); } catch (IOException e) { throw new RenderingException("IO error occured", e); @@ -743,6 +747,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext emitSuspendChecker(); } AsyncMethodPart part = methodNode.getBody().get(i); + end = true; + currentPart = i; part.getStatement().acceptVisitor(Renderer.this); writer.outdent(); } @@ -901,9 +907,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(SequentialStatement statement) { - for (Statement part : statement.getSequence()) { - part.acceptVisitor(this); - } + visitStatements(statement.getSequence()); } @Override @@ -924,9 +928,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } debugEmitter.emitCallSite(); writer.append(")").ws().append("{").softNewLine().indent(); - for (Statement part : statement.getConsequent()) { - part.acceptVisitor(this); - } + visitStatements(statement.getConsequent()); if (!statement.getAlternative().isEmpty()) { writer.outdent().append("}").ws(); if (statement.getAlternative().size() == 1 && @@ -936,9 +938,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext continue; } writer.append("else").ws().append("{").indent().softNewLine(); - for (Statement part : statement.getAlternative()) { - part.acceptVisitor(this); - } + visitStatements(statement.getAlternative()); } break; } @@ -973,16 +973,22 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.append("case ").append(condition).append(":").softNewLine(); } writer.indent(); + boolean oldEnd = end; for (Statement part : clause.getBody()) { + end = false; part.acceptVisitor(this); } + end = oldEnd; writer.outdent(); } if (statement.getDefaultClause() != null) { writer.append("default:").softNewLine().indent(); + boolean oldEnd = end; for (Statement part : statement.getDefaultClause()) { + end = false; part.acceptVisitor(this); } + end = oldEnd; writer.outdent(); } writer.outdent().append("}").softNewLine(); @@ -1015,9 +1021,12 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.append("true"); } writer.append(")").ws().append("{").softNewLine().indent(); + boolean oldEnd = end; for (Statement part : statement.getBody()) { + end = false; part.acceptVisitor(this); } + end = oldEnd; writer.outdent().append("}").softNewLine(); } catch (IOException e) { throw new RenderingException("IO error occured", e); @@ -1047,9 +1056,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext public void visit(BlockStatement statement) { try { writer.append(mapBlockId(statement.getId())).append(":").ws().append("{").softNewLine().indent(); - for (Statement part : statement.getBody()) { - part.acceptVisitor(this); - } + visitStatements(statement.getBody()); writer.outdent().append("}").softNewLine(); } catch (IOException e) { throw new RenderingException("IO error occured", e); @@ -2019,6 +2026,17 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } } + private void visitStatements(List statements) { + boolean oldEnd = end; + for (int i = 0; i < statements.size() - 1; ++i) { + end = false; + statements.get(i).acceptVisitor(this); + } + end = oldEnd; + statements.get(statements.size() - 1).acceptVisitor(this); + end = oldEnd; + } + @Override public void visit(TryCatchStatement statement) { try { @@ -2031,9 +2049,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext sequence.add(nextStatement); protectedBody = nextStatement.getProtectedBody(); } - for (Statement part : protectedBody) { - part.acceptVisitor(this); - } + visitStatements(protectedBody); writer.outdent().append("}").ws().append("catch").ws().append("($e)") .ws().append("{").indent().softNewLine(); writer.append("$je").ws().append("=").ws().append("$e.$javaException;").softNewLine(); @@ -2048,9 +2064,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.append(variableName(catchClause.getExceptionVariable())).ws().append("=").ws() .append("$je;").softNewLine(); } - for (Statement part : catchClause.getHandler()) { - part.acceptVisitor(this); - } + visitStatements(catchClause.getHandler()); writer.outdent().append("}").ws().append("else "); } writer.append("{").indent().softNewLine(); @@ -2065,9 +2079,13 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(GotoPartStatement statement) { try { - writer.append(pointerName()).ws().append("=").ws().append(statement.getPart()).append(";") - .softNewLine(); - writer.append("continue ").append(mainLoopName()).append(";").softNewLine(); + if (statement.getPart() != currentPart) { + writer.append(pointerName()).ws().append("=").ws().append(statement.getPart()).append(";") + .softNewLine(); + } + if (!end || statement.getPart() != currentPart + 1) { + writer.append("continue ").append(mainLoopName()).append(";").softNewLine(); + } } catch (IOException ex){ throw new RenderingException("IO error occured", ex); } diff --git a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java index a379c459a..c4205da2d 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java +++ b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java @@ -367,7 +367,7 @@ public class ProgramParser implements VariableDebugInformation { } // TODO: invokedynamic support (a great task, involving not only parser, but every layer of TeaVM) - private MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM4) { + private MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM5) { @Override public void visitVarInsn(int opcode, int local) { switch (opcode) { @@ -485,7 +485,12 @@ public class ProgramParser implements VariableDebugInformation { } @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc) { + public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { + throw new IllegalStateException("InvokeDynamic is not supported in TeaVM"); + } + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { switch (opcode) { case Opcodes.INVOKEINTERFACE: case Opcodes.INVOKEVIRTUAL: 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 142d1cc95..759869cbb 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -250,6 +250,14 @@ function $rt_createByteMultiArray(dimensions) { } return $rt_createMultiArrayImpl($rt_bytecls(), arrays, dimensions); } +function $rt_createCharMultiArray(dimensions) { + var arrays = new Array($rt_primitiveArrayCount(dimensions)); + var firstDim = dimensions[0] | 0; + for (var i = 0 | 0; i < arrays.length; i = (i + 1) | 0) { + arrays[i] = $rt_createCharArray(firstDim); + } + return $rt_createMultiArrayImpl($rt_charcls(), arrays, dimensions); +} function $rt_createBooleanMultiArray(dimensions) { var arrays = new Array($rt_primitiveArrayCount(dimensions)); var firstDim = dimensions[0] | 0; diff --git a/teavm-samples/pom.xml b/teavm-samples/pom.xml index 6513d89c4..4dd090a69 100644 --- a/teavm-samples/pom.xml +++ b/teavm-samples/pom.xml @@ -35,5 +35,6 @@ teavm-samples-storage teavm-samples-video teavm-samples-async + teavm-samples-kotlin \ No newline at end of file diff --git a/teavm-samples/teavm-samples-kotlin/.gitignore b/teavm-samples/teavm-samples-kotlin/.gitignore new file mode 100644 index 000000000..8bd3a0588 --- /dev/null +++ b/teavm-samples/teavm-samples-kotlin/.gitignore @@ -0,0 +1,4 @@ +/target/ +/.settings/ +/.classpath +/.project diff --git a/teavm-samples/teavm-samples-kotlin/pom.xml b/teavm-samples/teavm-samples-kotlin/pom.xml new file mode 100644 index 000000000..7e7147a5d --- /dev/null +++ b/teavm-samples/teavm-samples-kotlin/pom.xml @@ -0,0 +1,131 @@ + + + 4.0.0 + + + org.teavm + teavm-samples + 0.3.0-SNAPSHOT + + teavm-samples-kotlin + + war + + TeaVM Kotlin web application + A sample application written in Kotlin and compiled by TeaVM + + + 0.11.91.1 + + + + + org.jetbrains.kotlin + kotlin-stdlib + ${kotlin.version} + + + junit + junit + test + + + org.teavm + teavm-classlib + ${project.version} + provided + + + org.teavm + teavm-dom + ${project.version} + provided + + + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/test/kotlin + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + + org.teavm + teavm-maven-plugin + ${project.version} + + + web-client + prepare-package + + build-javascript + + + ${project.build.directory}/generated/js/teavm + org.teavm.samples.kotlin.KotlinPackage + SEPARATE + false + true + true + true + + + + + + maven-war-plugin + 2.4 + + + + ${project.build.directory}/generated/js + + + + + + org.apache.maven.plugins + maven-source-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-kotlin/src/main/kotlin/Hello.kt b/teavm-samples/teavm-samples-kotlin/src/main/kotlin/Hello.kt new file mode 100644 index 000000000..f71b3bcf6 --- /dev/null +++ b/teavm-samples/teavm-samples-kotlin/src/main/kotlin/Hello.kt @@ -0,0 +1,15 @@ +package org.teavm.samples.kotlin + +import org.teavm.jso.* +import org.teavm.dom.browser.* +import org.teavm.dom.html.* +import org.teavm.dom.events.* + +fun main(args : Array) { + var window = JS.getGlobal() as Window; + var document = window.getDocument(); + + document.getElementById("hello-kotlin").addEventListener("click", EventListener() { + window.alert("Hello, developer!"); + }) +} diff --git a/teavm-samples/teavm-samples-kotlin/src/main/webapp/WEB-INF/web.xml b/teavm-samples/teavm-samples-kotlin/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..bfc410b12 --- /dev/null +++ b/teavm-samples/teavm-samples-kotlin/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,21 @@ + + + + \ No newline at end of file diff --git a/teavm-samples/teavm-samples-kotlin/src/main/webapp/index.html b/teavm-samples/teavm-samples-kotlin/src/main/webapp/index.html new file mode 100644 index 000000000..988fa4e9a --- /dev/null +++ b/teavm-samples/teavm-samples-kotlin/src/main/webapp/index.html @@ -0,0 +1,31 @@ + + + + Hello kotlin + + + + + +

+ +

This application was compiled by TeaVM from the following Kotlin source:

+
+package org.teavm.samples.kotlin
+
+import org.teavm.jso.*
+import org.teavm.dom.browser.*
+import org.teavm.dom.html.*
+import org.teavm.dom.events.*
+
+fun main(args : Array<String>) {
+    var window = JS.getGlobal() as Window;
+    var document = window.getDocument();
+
+    document.getElementById("hello-kotlin").addEventListener("click", EventListener<MouseEvent>() {
+       window.alert("Hello, developer!");
+    })
+}
+    
+ + \ No newline at end of file