diff --git a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/AstWriter.java b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/AstWriter.java index 27ac6aeba..0d96c87dd 100644 --- a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/AstWriter.java +++ b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/AstWriter.java @@ -162,7 +162,7 @@ public class AstWriter { print((ArrayComprehension) node); break; case Token.GETPROP: - print((PropertyGet) node, precedence); + print((PropertyGet) node); break; case Token.GENEXPR: print((GeneratorExpression) node); @@ -208,7 +208,7 @@ public class AstWriter { print((ConditionalExpression) node, precedence); break; case Token.GETELEM: - print((ElementGet) node, precedence); + print((ElementGet) node); break; case Token.LETEXPR: print((LetNode) node); @@ -425,6 +425,7 @@ public class AstWriter { print(cc.getCatchCondition()); } writer.append(')'); + print(cc.getBody()); } if (node.getFinallyBlock() != null) { writer.ws().append("finally "); @@ -469,48 +470,40 @@ public class AstWriter { writer.append(';'); } - private void print(ElementGet node, int precedence) throws IOException { - if (precedence < PRECEDENCE_MEMBER) { - writer.append('('); - } + private void print(ElementGet node) throws IOException { print(node.getTarget(), PRECEDENCE_MEMBER); - if (precedence < PRECEDENCE_MEMBER) { - writer.append(')'); - } writer.append('['); print(node.getElement()); writer.append(']'); } - private void print(PropertyGet node, int precedence) throws IOException { - if (precedence < PRECEDENCE_MEMBER) { - writer.append('('); - } - print(node.getLeft()); - if (precedence < PRECEDENCE_MEMBER) { - writer.append(')'); - } + private void print(PropertyGet node) throws IOException { + print(node.getLeft(), PRECEDENCE_MEMBER); writer.ws().append('.').ws(); print(node.getRight()); } private void print(FunctionCall node, int precedence) throws IOException { - if (node instanceof NewExpression) { - writer.append("new "); - } if (precedence < PRECEDENCE_FUNCTION) { writer.append('('); } - print(node.getTarget(), PRECEDENCE_FUNCTION); - if (precedence < PRECEDENCE_FUNCTION) { - writer.append(')'); + int innerPrecedence = node instanceof NewExpression ? PRECEDENCE_FUNCTION - 1 : PRECEDENCE_FUNCTION; + if (node instanceof NewExpression) { + writer.append("new "); } + print(node.getTarget(), innerPrecedence); writer.append('('); printList(node.getArguments()); writer.append(')'); if (node instanceof NewExpression) { writer.ws(); - print(((NewExpression) node).getInitializer()); + NewExpression newExpr = (NewExpression) node; + if (newExpr.getInitializer() != null) { + print(newExpr.getInitializer()); + } + } + if (precedence < PRECEDENCE_FUNCTION) { + writer.append(')'); } } @@ -526,7 +519,6 @@ public class AstWriter { if (precedence < PRECEDENCE_COND) { writer.append(')'); } - print(node.getTestExpression(), precedence); } private void printList(List nodes) throws IOException { @@ -613,19 +605,19 @@ public class AstWriter { print(node.getElements().get(i)); } } - printList(node.getElements()); writer.append('}'); } private void print(ObjectProperty node) throws IOException { - StringBuilder sb = new StringBuilder(); if (node.isGetterMethod()) { - sb.append("get "); + writer.append("get "); } else if (node.isSetterMethod()) { - sb.append("set "); + writer.append("set "); } print(node.getLeft()); - writer.ws().append(':').ws(); + if (!node.isMethod()) { + writer.ws().append(':').ws(); + } print(node.getRight()); } @@ -633,7 +625,7 @@ public class AstWriter { if (!node.isMethod()) { writer.append("function"); } - if (node.getFunctionName().getString() != null) { + if (node.getFunctionName() != null) { writer.append(' '); print(node.getFunctionName()); } @@ -671,6 +663,11 @@ public class AstWriter { private void printUnary(UnaryExpression node, int precedence) throws IOException { int innerPrecedence = node.isPostfix() ? PRECEDENCE_POSTFIX : PRECEDENCE_PREFIX; + + if (innerPrecedence > precedence) { + writer.append('('); + } + if (!node.isPostfix()) { writer.append(AstNode.operatorToString(node.getType())); if (requiresWhitespaces(node.getType())) { @@ -678,19 +675,15 @@ public class AstWriter { } } - if (innerPrecedence > precedence) { - writer.append('('); - } - print(node.getOperand(), innerPrecedence); - if (innerPrecedence > precedence) { - writer.append(')'); - } - if (node.isPostfix()) { writer.append(AstNode.operatorToString(node.getType())); } + + if (innerPrecedence > precedence) { + writer.append(')'); + } } private void printInfix(InfixExpression node, int precedence) throws IOException { @@ -760,7 +753,7 @@ public class AstWriter { print(node.getRight(), rightPrecedence); if (innerPrecedence > precedence) { - writer.append('('); + writer.append(')'); } } diff --git a/teavm-jso-impl/src/test/java/org/teavm/jso/plugin/AstWriterTest.java b/teavm-jso-impl/src/test/java/org/teavm/jso/plugin/AstWriterTest.java index 3bfd3281d..22b786acd 100644 --- a/teavm-jso-impl/src/test/java/org/teavm/jso/plugin/AstWriterTest.java +++ b/teavm-jso-impl/src/test/java/org/teavm/jso/plugin/AstWriterTest.java @@ -20,8 +20,8 @@ import static org.junit.Assert.*; import java.io.IOException; import java.io.StringReader; import org.junit.Test; -import org.junit.experimental.theories.suppliers.TestedOn; import org.mozilla.javascript.CompilerEnvirons; +import org.mozilla.javascript.Context; import org.mozilla.javascript.ast.AstRoot; import org.teavm.codegen.SourceWriter; import org.teavm.codegen.SourceWriterBuilder; @@ -94,10 +94,16 @@ public class AstWriterTest { assertThat(transform("{ foo(); bar(); }"), is("{foo();bar();}")); } + @Test + public void writesTryCatch() throws IOException { + assertThat(transform("try { foo(); } catch (e) { alert(e); }"), is("try {foo();}catch(e){alert(e);}")); + assertThat(transform("try { foo(); } finally { close(); }"), is("try {foo();}finally {close();}")); + } + @Test public void writesFor() throws IOException { - assertThat(transform("for (var i = 0; i < array.length; ++i) foo(array[i]);"), - is("for(var i=0;i b ? 1 : 0;"), is("return ab?1:0;")); + assertThat(transform("return a < b ? -1 : (a > b ? 1 : 0);"), is("return ab?1:0;")); + assertThat(transform("return (a < b ? x == y : x != y) ? 1 : 0;"), is("return (a y ? x : y) : z"), is("return ay?x:y):z;")); + } + + @Test + public void writesRegExp() throws IOException { + assertThat(transform("return /[a-z]+/.match(text);"), is("return /[a-z]+/.match(text);")); + assertThat(transform("return /[a-z]+/ig.match(text);"), is("return /[a-z]+/ig.match(text);")); + } + + @Test + public void writesArrayLiteral() throws IOException { + assertThat(transform("return [];"), is("return [];")); + assertThat(transform("return [a, b + c];"), is("return [a,b+c];")); + } + + @Test + public void writesObjectLiteral() throws IOException { + assertThat(transform("return {};"), is("return {};")); + assertThat(transform("return { foo : bar };"), is("return {foo:bar};")); + assertThat(transform("return { foo : bar };"), is("return {foo:bar};")); + assertThat(transform("return { _foo : bar, get foo() { return this._foo; } };"), + is("return {_foo:bar,get foo(){return this._foo;}};")); + } + + @Test + public void writesFunction() throws IOException { + assertThat(transform("return function f(x, y) { return x + y; };"), + is("return function f(x,y){return x+y;};")); + } + + @Test + public void writesUnary() throws IOException { + assertThat(transform("return -a;"), is("return -a;")); + assertThat(transform("return -(a + b);"), is("return -(a+b);")); + assertThat(transform("return -a + b;"), is("return -a+b;")); + assertThat(transform("return (-a) + b;"), is("return -a+b;")); + assertThat(transform("return (-f)(x);"), is("return (-f)(x);")); + assertThat(transform("return typeof a;"), is("return typeof a;")); + } + + @Test + public void writesPostfix() throws IOException { + assertThat(transform("return a++;"), is("return a++;")); + } + + @Test + public void respectsPrecedence() throws IOException { + assertThat(transform("return a + b + c;"), is("return a+b+c;")); + assertThat(transform("return (a + b) + c;"), is("return a+b+c;")); + assertThat(transform("return a + (b + c);"), is("return a+b+c;")); + assertThat(transform("return a - b + c;"), is("return a-b+c;")); + assertThat(transform("return (a - b) + c;"), is("return a-b+c;")); + assertThat(transform("return a - (b + c);"), is("return a-(b+c);")); + } + private String transform(String text) throws IOException { + sb.setLength(0); CompilerEnvirons env = new CompilerEnvirons(); env.setRecoverFromErrors(true); + env.setLanguageVersion(Context.VERSION_1_8); JSParser factory = new JSParser(env); factory.enterFunction(); AstRoot rootNode = factory.parse(new StringReader(text), null, 0);