diff --git a/teavm-jso-impl/pom.xml b/teavm-jso-impl/pom.xml index cfc991f5f..641ddd518 100644 --- a/teavm-jso-impl/pom.xml +++ b/teavm-jso-impl/pom.xml @@ -38,6 +38,11 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xs teavm-jso ${project.version} + + org.mozilla + rhino + 1.7.7 + junit junit diff --git a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JSBodyGenerator.java b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JSBodyGenerator.java index 0e496c4e7..4afc70de1 100644 --- a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JSBodyGenerator.java +++ b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/JSBodyGenerator.java @@ -16,11 +16,22 @@ package org.teavm.jso.plugin; import java.io.IOException; +import java.io.StringReader; import java.util.List; +import org.mozilla.javascript.CompilerEnvirons; +import org.mozilla.javascript.IRFactory; +import org.mozilla.javascript.ast.AstNode; +import org.mozilla.javascript.ast.AstRoot; +import org.mozilla.javascript.ast.NodeVisitor; import org.teavm.codegen.SourceWriter; import org.teavm.javascript.spi.Generator; import org.teavm.javascript.spi.GeneratorContext; -import org.teavm.model.*; +import org.teavm.model.AnnotationReader; +import org.teavm.model.AnnotationValue; +import org.teavm.model.CallLocation; +import org.teavm.model.ClassReader; +import org.teavm.model.MethodReader; +import org.teavm.model.MethodReference; /** * @@ -37,51 +48,24 @@ public class JSBodyGenerator implements Generator { int bodyParamCount = isStatic ? method.parameterCount() : method.parameterCount() - 1; - writer.append("if (!").appendMethodBody(methodRef).append(".$native)").ws().append('{').indent().newLine(); - writer.appendMethodBody(methodRef).append(".$native").ws().append('=').ws().append("function("); - int count = method.parameterCount(); - for (int i = 0; i < count; ++i) { - if (i > 0) { - writer.append(',').ws(); - } - writer.append('_').append(context.getParameterName(i + 1)); + CompilerEnvirons env = new CompilerEnvirons(); + env.setRecoverFromErrors(true); + IRFactory factory = new IRFactory(env, new TeaVMErrorReporter(context.getDiagnostics(), + new CallLocation(methodRef))); + String script = annot.getValue("script").getString(); + AstRoot rootNode; + try { + rootNode = factory.parse(new StringReader(script), null, 0); + } catch (IOException e) { + context.getDiagnostics().error(new CallLocation(methodRef), "IO error parsing JSBody script"); + return; } - writer.append(')').ws().append('{').softNewLine().indent(); - writer.append("return (function("); - for (int i = 0; i < bodyParamCount; ++i) { - if (i > 0) { - writer.append(',').ws(); + rootNode.visit(new NodeVisitor() { + @Override + public boolean visit(AstNode node) { + return false; } - String name = paramNames.get(i).getString(); - writer.append(name); - } - writer.append(')').ws().append('{').softNewLine().indent(); - writer.append(annot.getValue("script").getString()).softNewLine(); - writer.outdent().append("})"); - if (!isStatic) { - writer.append(".call"); - } - writer.append('('); - for (int i = 0; i < count; ++i) { - if (i > 0) { - writer.append(',').ws(); - } - writer.append('_').append(context.getParameterName(i + 1)); - } - writer.append(");").softNewLine(); - writer.outdent().append("};").softNewLine(); - writer.appendMethodBody(methodRef).ws().append('=').ws().appendMethodBody(methodRef).append(".$native;") - .softNewLine(); - writer.outdent().append("}").softNewLine(); - - writer.append("return ").appendMethodBody(methodRef).append('('); - for (int i = 0; i < count; ++i) { - if (i > 0) { - writer.append(',').ws(); - } - writer.append(context.getParameterName(i + 1)); - } - writer.append(");").softNewLine(); + }); } } diff --git a/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/TeaVMErrorReporter.java b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/TeaVMErrorReporter.java new file mode 100644 index 000000000..8a95374de --- /dev/null +++ b/teavm-jso-impl/src/main/java/org/teavm/jso/plugin/TeaVMErrorReporter.java @@ -0,0 +1,53 @@ +/* + * 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.jso.plugin; + +import org.mozilla.javascript.ErrorReporter; +import org.mozilla.javascript.EvaluatorException; +import org.teavm.diagnostics.Diagnostics; +import org.teavm.model.CallLocation; + +/** + * + * @author Alexey Andreev + */ +public class TeaVMErrorReporter implements ErrorReporter { + private Diagnostics diagnostics; + private CallLocation location; + + public TeaVMErrorReporter(Diagnostics diagnostics, CallLocation location) { + this.diagnostics = diagnostics; + this.location = location; + } + + @Override + public void warning(String message, String sourceName, int line, String lineSource, int lineOffset) { + diagnostics.warning(location, "Error in @JSBody script line " + line + ", char " + lineOffset + + ": " + message); + } + + @Override + public void error(String message, String sourceName, int line, String lineSource, int lineOffset) { + diagnostics.error(location, "Error in @JSBody script line " + line + ", char " + lineOffset + + ": " + message); + } + + @Override + public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, + int lineOffset) { + return null; + } +}